
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.IO;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace PlanetExpress.Tools {
	
	
	public class FontRenderClass {
		
		private Font ClassFont;
		private Encoding ClassEncoding;
		private RectangleF[] Chars = new RectangleF[256];
		private TexClass FontTex;
		
		private Bitmap img;
		public FontRenderClass(Font f, Encoding e) {
			ClassFont = f;
			ClassEncoding = e;
			#region вычисляем размер изображения			
			int imgw = 0;
			int imgh = 0;
			{
				Bitmap tmpi = new Bitmap(1, 1);
				Graphics g = Graphics.FromImage(tmpi);
				
				int rowWidth = 0;
				int rowHeight = 0;
				for (int c=0; c<16; c++) {
					for (int r=0; r<16; r++) {
						byte ch = (byte)(r + c * 16);
						if (ch == 0) continue;
						try {							
							string chText =
								ClassEncoding.GetString(new byte[]{ch}, 0, 1);
							SizeF s = g.MeasureString(chText, ClassFont);
							
							Chars[ch] =
								new RectangleF(rowWidth, imgh, s.Width, s.Height);
							
							rowWidth += (int)s.Width + 1;
							if (s.Height > rowHeight) rowHeight = (int) s.Height;							
						} catch { }						
					}
					imgh += rowHeight;
					rowHeight = 0;
					if (rowWidth > imgw) imgw = rowWidth;
					rowWidth = 0;
				}
			}			
			#endregion
			
			#region  создание карты шрифта	
			img = new Bitmap(imgw, imgh);
			{				
				Graphics g = Graphics.FromImage(img);
				for (int c=0; c<16; c++) {
					for (int r=0; r<16; r++) {
						byte ch = (byte)(r + c * 16);
						if (ch == 0) continue;
						try {							
							string chText =
								ClassEncoding.GetString(new byte[]{ch}, 0, 1);
							g.DrawString(chText,
							             ClassFont,
							             Brushes.White,
							             Chars[ch]);
						} catch { }						
					}
				}
			}	
			FontTex = TexMan.LoadTexture(img);
			#endregion
		}
		
		public float Render(string text, float x, float y, float w) {
			float left = 0;
			float top = 0f;
			float rowH = 0;
			GL.PushMatrix(); {
				GL.Translate(x, y, 0f);
				byte[] buff = ClassEncoding.GetBytes(text);				
				foreach (byte c in buff) {
					RectangleF r = Chars[c];
					if (w == 0 || left + r.Width <= w) {
						FontTex.Render(left, top, r);
						left += r.Width;
						if (r.Height > rowH) rowH = r.Height;
					} else {
						left = 0;
						top += rowH;
						
						FontTex.Render(left, top, r);
						left += r.Width;	
						rowH = r.Height;
					}
				}
			}	GL.PopMatrix();
			return top + rowH;
		}
		
		public void Save(string fileName) {
			FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate);
			Save(fs);
			fs.Close();
		}
		
		public void Save(Stream s) {
			BinaryWriter bw = new BinaryWriter(s);
			//bw.Write(Encoding.ASCII.GetBytes("fnt"));
			img.Save(s, ImageFormat.Png);
			foreach (RectangleF r in Chars) {
				bw.Write((Single)r.Left);	
				bw.Write((Single)r.Top);
				bw.Write((Single)r.Width);
				bw.Write((Single)r.Height);
			}
		}
		
		public void Load(string fileName) {
			FileStream fs = new FileStream(fileName, FileMode.Open);
			Load(fs);
			fs.Close();
		}
		
		public void Load(Stream s) {
			BinaryReader br = new BinaryReader(s);
			//if (Encoding.ASCII.GetString(br.ReadBytes(3)) != "fnt") throw new Exception("Bad font file.");
			img = new Bitmap(s);
			for (int i=0; i<Chars.Length; i++) {
				float l = br.ReadSingle();
				float t = br.ReadSingle();
				float w = br.ReadSingle();
				float h = br.ReadSingle();
				Chars[i] = new RectangleF(l, t, w, h);
			}
			FontTex = TexMan.LoadTexture(img);
		}
	}
}
