diff --git a/Source/OpenTK/Fonts/DisplayListTextPrinter.cs b/Source/OpenTK/Fonts/DisplayListTextPrinter.cs
new file mode 100644
index 00000000..304cad90
--- /dev/null
+++ b/Source/OpenTK/Fonts/DisplayListTextPrinter.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using OpenTK.OpenGL;
+
+namespace OpenTK.Fonts
+{
+ ///
+ /// Provides text printing through OpenGL 1.1 Display Lists.
+ ///
+ class DisplayListTextPrinter : ITextPrinterImplementation
+ {
+ #region IPrinter Members
+
+ public TextHandle Load(OpenTK.Math.Vector2[] vertices, ushort[] indices)
+ {
+ DisplayListTextHandle handle = new DisplayListTextHandle(GL.GenLists(1));
+
+ GL.NewList(handle.Handle, OpenTK.OpenGL.Enums.ListMode.Compile);
+ GL.Begin(OpenTK.OpenGL.Enums.BeginMode.Triangles);
+
+ foreach (ushort index in indices)
+ {
+ GL.TexCoord2(vertices[index + 1]);
+ GL.Vertex2(vertices[index]);
+ }
+
+ GL.End();
+ GL.EndList();
+
+ return handle;
+ }
+
+ public void Draw(TextHandle handle)
+ {
+ GL.CallList(handle.Handle);
+ }
+
+ #endregion
+ }
+
+ public class DisplayListTextHandle : TextHandle
+ {
+ public DisplayListTextHandle(int handle) : base(handle) { }
+ }
+}
diff --git a/Source/OpenTK/Fonts/IPrinterImplementation.cs b/Source/OpenTK/Fonts/IPrinterImplementation.cs
new file mode 100644
index 00000000..42303747
--- /dev/null
+++ b/Source/OpenTK/Fonts/IPrinterImplementation.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using OpenTK.Math;
+
+namespace OpenTK.Fonts
+{
+ ///
+ /// Defines the interface for TextPrinter implementations.
+ ///
+ interface ITextPrinterImplementation
+ {
+ TextHandle Load(Vector2[] vertices, ushort[] indices);
+ void Draw(TextHandle handle);
+ }
+}
diff --git a/Source/OpenTK/Fonts/TextHandle.cs b/Source/OpenTK/Fonts/TextHandle.cs
new file mode 100644
index 00000000..be4946fe
--- /dev/null
+++ b/Source/OpenTK/Fonts/TextHandle.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace OpenTK.Fonts
+{
+ public class TextHandle
+ {
+ internal TextHandle(int handle)
+ {
+ Handle = handle;
+ }
+
+ public readonly int Handle;
+ internal TextureFont font;
+
+ public override string ToString()
+ {
+ return String.Format("TextHandle: {0}", Handle);
+ }
+ }
+}
diff --git a/Source/OpenTK/Fonts/TextPrinter.cs b/Source/OpenTK/Fonts/TextPrinter.cs
index 4400e513..edaf5b75 100644
--- a/Source/OpenTK/Fonts/TextPrinter.cs
+++ b/Source/OpenTK/Fonts/TextPrinter.cs
@@ -9,11 +9,11 @@ using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Text.RegularExpressions;
+using System.Runtime.InteropServices;
using OpenTK.Math;
using OpenTK.OpenGL;
using OpenTK.OpenGL.Enums;
-using System.Runtime.InteropServices;
namespace OpenTK.Fonts
@@ -27,7 +27,7 @@ namespace OpenTK.Fonts
//static char[] split_chars = new char[] { ' ', '\n', '\t', ',', '.', '/', '?', '!', ';', '\\', '-', '+', '*', '=' };
static bool use_vbo, use_arb_vbo, use_display_list;
static bool functionality_checked = false;
- static IPrinter printer;
+ static ITextPrinterImplementation printer;
#region --- Constructor ---
@@ -43,11 +43,12 @@ namespace OpenTK.Fonts
///
static void CheckNeededFunctionality()
{
- printer =
- GL.SupportsExtension("VERSION_1_5") ? new VboPrinter() :
+ printer = new DisplayListTextPrinter();
+ /*
+ GL.SupportsExtension("VERSION_1_5") ? new VboTextPrinter() :
GL.SupportsExtension("ARB_vertex_buffer_object") ? null :
GL.SupportsExtension("VERSION_1_1") ? null : null;
-
+ */
if (printer == null)
throw new NotSupportedException("DefaultLayoutProvider requires at least OpenGL 1.1 support.");
@@ -79,8 +80,8 @@ namespace OpenTK.Fonts
if (text == null)
throw new ArgumentNullException("Parameter cannot be null.", "text");
- if (text.Length > 4096)
- throw new ArgumentOutOfRangeException("text", text.Length, "Text length must be between 1 and 4096 characters");
+ if (text.Length > 8192)
+ throw new ArgumentOutOfRangeException("text", text.Length, "Text length must be between 1 and 8192 characters");
Vector2[] vertices = new Vector2[8 * text.Length]; // Interleaved, vertex, texcoord, vertex, etc...
ushort[] indices = new ushort[6 * text.Length];
@@ -90,6 +91,8 @@ namespace OpenTK.Fonts
float char_width, char_height, measured_width, measured_height;
int texture;
+ font.LoadGlyphs(text);
+
// Every character comprises of 4 vertices, forming two triangles. We generate an index array which
// indexes vertices in a triangle-strip fashion. To create a single strip for the whole string, we
// need to add a degenerate triangle (0 height) to connect the last vertex of the previous line with
@@ -168,7 +171,8 @@ namespace OpenTK.Fonts
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
- GL.Enable(EnableCap.Blend);
+ //GL.Disable(EnableCap.Texture2d);
+
GL.BindTexture(TextureTarget.Texture2d, handle.font.Texture);
printer.Draw(handle);
@@ -179,78 +183,4 @@ namespace OpenTK.Fonts
#endregion
}
-
- public class TextHandle
- {
- internal TextHandle(int handle)
- {
- Handle = handle;
- }
-
- public readonly int Handle;
- internal TextureFont font;
- }
-
- class VboTextHandle : TextHandle
- {
- public VboTextHandle(int handle) : base(handle) { }
-
- internal int vbo_id; // vertex buffer object id.
- internal int ebo_id; // index buffer object id.
- internal int element_count; // Number of elements in the ebo.
- }
-
- interface IPrinter
- {
- TextHandle Load(Vector2[] vertices, ushort[] indices);
- void Draw(TextHandle handle);
- }
-
- class VboPrinter : IPrinter
- {
- static int allocated_handles;
- static int vector2_size = Marshal.SizeOf(new Vector2());
-
- #region --- IPrinter Members ---
-
- public TextHandle Load(Vector2[] vertices, ushort[] indices)
- {
- VboTextHandle handle = new VboTextHandle(++allocated_handles);
- GL.GenBuffers(1, out handle.vbo_id);
- GL.GenBuffers(1, out handle.ebo_id);
-
- GL.BindBuffer(Version15.ArrayBuffer, handle.vbo_id);
- GL.BufferData(Version15.ArrayBuffer, (IntPtr)(vertices.Length * vector2_size), vertices,
- Version15.StaticDraw);
-
- GL.BindBuffer(Version15.ElementArrayBuffer, handle.ebo_id);
- GL.BufferData(Version15.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(ushort)), indices,
- Version15.StaticDraw);
- handle.element_count = indices.Length;
-
- return handle;
- }
-
- public void Draw(TextHandle handle)
- {
- VboTextHandle vbo = (VboTextHandle)handle;
-
- GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);
-
- GL.BindBuffer(Version15.StaticDraw, vbo.vbo_id);
- GL.BindBuffer(Version15.ElementArrayBuffer, vbo.ebo_id);
-
- GL.EnableClientState(EnableCap.VertexArray);
- GL.EnableClientState(EnableCap.TextureCoordArray);
-
- GL.TexCoordPointer(2, TexCoordPointerType.Float, vector2_size, (IntPtr)vector2_size);
- GL.VertexPointer(2, VertexPointerType.Float, vector2_size, IntPtr.Zero);
-
- GL.DrawElements(BeginMode.Triangles, vbo.element_count, All.UnsignedShort, IntPtr.Zero);
-
- GL.PopClientAttrib();
- }
-
- #endregion
- }
}
diff --git a/Source/OpenTK/Fonts/TextureFont.cs b/Source/OpenTK/Fonts/TextureFont.cs
index 39936da3..d81fe3b3 100644
--- a/Source/OpenTK/Fonts/TextureFont.cs
+++ b/Source/OpenTK/Fonts/TextureFont.cs
@@ -15,15 +15,17 @@ using OpenTK.OpenGL;
using OpenTK.OpenGL.Enums;
using System.Drawing.Imaging;
using OpenTK.Platform;
+using System.Drawing;
namespace OpenTK.Fonts
{
public class TextureFont : IFont
{
- System.Drawing.Font font;
+ Font font;
Dictionary loaded_glyphs = new Dictionary(64);
- System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(new System.Drawing.Bitmap(1, 1));
+ Bitmap bmp;
+ Graphics gfx;
static int texture;
static TexturePacker pack;
static int texture_width, texture_height;
@@ -41,6 +43,9 @@ namespace OpenTK.Fonts
throw new ArgumentNullException("font", "Argument to TextureFont constructor cannot be null.");
this.font = font;
+
+ bmp = new Bitmap(font.Height * 2, font.Height * 2);
+ gfx = Graphics.FromImage(bmp);
}
#endregion
@@ -94,13 +99,28 @@ namespace OpenTK.Fonts
#endregion
+ #region public void LoadGlyph(char glyph)
+
+ ///
+ /// Prepares the specified glyph for rendering.
+ ///
+ /// The glyph to prepare for rendering.
+ public void LoadGlyph(char glyph)
+ {
+ Box2 rect = new Box2();
+ if (!loaded_glyphs.ContainsKey(glyph))
+ LoadGlyph(glyph, out rect);
+ }
+
+ #endregion
+
#region private void LoadGlyph(char c, out Box2 rectangle)
///
/// Adds a glyph to the texture packer.
///
/// The character of the glyph.
- /// A RectangleF that will hold the data for this glyph.
+ /// An OpenTK.Math.Box2 that will hold the data for this glyph.
private void LoadGlyph(char c, out Box2 rectangle)
{
if (pack == null)
@@ -109,25 +129,48 @@ namespace OpenTK.Fonts
Glyph g = new Glyph(c, font);
System.Drawing.Rectangle rect = pack.Add(g);
- using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(
- rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
- using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(bmp))
+ //using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
+ //using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(bmp))
{
- // Upload texture data.
GL.BindTexture(TextureTarget.Texture2d, texture);
- //gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
- //gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
- gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
- gfx.TextContrast = 0;
+ // Set font rendering mode. Smal sizes look blurry without gridfitting, so turn
+ // that on. Increasing contrast also seems to help.
+ if (font.Size <= 18.0f)
+ {
+ gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
+ gfx.TextContrast = 1;
+ }
+ else
+ {
+ gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
+ gfx.TextContrast = 0;
+ }
+
gfx.Clear(System.Drawing.Color.Transparent);
gfx.DrawString(g.Character.ToString(), g.Font, System.Drawing.Brushes.White, 0.0f, 0.0f);
-
+ /*
BitmapData bmp_data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, rect.Width, rect.Height), ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexSubImage2D(TextureTarget.Texture2d, 0, rect.Left, rect.Top, rect.Width, rect.Height,
OpenTK.OpenGL.Enums.PixelFormat.Rgba, PixelType.UnsignedByte, bmp_data.Scan0);
bmp.UnlockBits(bmp_data);
+ */
+
+ int[] data = new int[rect.Width * rect.Height];
+ for (int y = 0; y < rect.Height; y++)
+ {
+ for (int x = 0; x < rect.Width; x++)
+ {
+ data[y * rect.Width + x] = bmp.GetPixel(x, y).ToArgb();
+ }
+ }
+ unsafe
+ {
+ fixed (int* ptr = data)
+ GL.TexSubImage2D(TextureTarget.Texture2d, 0, rect.Left, rect.Top, rect.Width, rect.Height,
+ OpenTK.OpenGL.Enums.PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)ptr);
+ }
rectangle = new Box2(
rect.Left / (float)texture_width,
@@ -180,6 +223,18 @@ namespace OpenTK.Fonts
#endregion
+ #region public float Width
+
+ ///
+ /// Gets a float indicating the default line spacing of this font.
+ ///
+ public float Width
+ {
+ get { return font.SizeInPoints; }
+ }
+
+ #endregion
+
#region internal int Texture
///
diff --git a/Source/OpenTK/Fonts/VboTextPrinter.cs b/Source/OpenTK/Fonts/VboTextPrinter.cs
new file mode 100644
index 00000000..2b60e4a1
--- /dev/null
+++ b/Source/OpenTK/Fonts/VboTextPrinter.cs
@@ -0,0 +1,99 @@
+#region --- License ---
+/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
+ * See license.txt for license info
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+using OpenTK.OpenGL;
+using OpenTK.Math;
+using OpenTK.OpenGL.Enums;
+
+namespace OpenTK.Fonts
+{
+ ///
+ /// Provides text printing through OpenGL 1.5 vertex buffer objects.
+ ///
+ class VboTextPrinter : ITextPrinterImplementation
+ {
+ static int allocated_handles;
+ static int vector2_size = Marshal.SizeOf(new Vector2());
+
+ #region --- IPrinter Members ---
+
+ public TextHandle Load(Vector2[] vertices, ushort[] indices)
+ {
+ VboTextHandle handle = new VboTextHandle(++allocated_handles);
+
+ GL.GenBuffers(1, out handle.vbo_id);
+ GL.BindBuffer(Version15.ArrayBuffer, handle.vbo_id);
+ GL.BufferData(Version15.ArrayBuffer, (IntPtr)(vertices.Length * vector2_size), vertices,
+ Version15.StaticDraw);
+ GL.BindBuffer(Version15.ArrayBuffer, 0);
+
+ GL.GenBuffers(1, out handle.ebo_id);
+ GL.BindBuffer(Version15.ElementArrayBuffer, handle.ebo_id);
+ GL.BufferData(Version15.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(ushort)), indices,
+ Version15.StaticDraw);
+ GL.BindBuffer(Version15.ElementArrayBuffer, 0);
+
+ handle.element_count = indices.Length;
+ return handle;
+ }
+
+ public void Draw(TextHandle handle)
+ {
+ VboTextHandle vbo = (VboTextHandle)handle;
+
+ //GL.PushClientAttrib(ClientAttribMask.ClientVertexArrayBit);
+
+ //GL.EnableClientState(EnableCap.TextureCoordArray);
+ GL.EnableClientState(EnableCap.VertexArray);
+
+ GL.BindBuffer(Version15.StaticDraw, vbo.vbo_id);
+ GL.BindBuffer(Version15.ElementArrayBuffer, vbo.ebo_id);
+
+ GL.TexCoordPointer(2, TexCoordPointerType.Float, vector2_size, (IntPtr)vector2_size);
+ GL.VertexPointer(2, VertexPointerType.Float, vector2_size, IntPtr.Zero);
+
+ GL.DrawElements(BeginMode.Triangles, vbo.element_count, All.UnsignedShort, IntPtr.Zero);
+ //GL.DrawArrays(BeginMode.LineLoop, 0, vbo.element_count);
+
+ GL.BindBuffer(Version15.ArrayBuffer, 0);
+ GL.BindBuffer(Version15.ElementArrayBuffer, 0);
+
+ GL.DisableClientState(EnableCap.VertexArray);
+ //GL.DisableClientState(EnableCap.TextureCoordArray);
+
+ //GL.PopClientAttrib();
+ }
+
+ #endregion
+ }
+
+ #region class VboTextHandle : TextHandle
+
+ ///
+ /// Contains the necessary information to print text through the VboTextPrinter implementation.
+ ///
+ class VboTextHandle : TextHandle
+ {
+ public VboTextHandle(int handle) : base(handle) { }
+
+ internal int vbo_id; // vertex buffer object id.
+ internal int ebo_id; // index buffer object id.
+ internal int element_count; // Number of elements in the ebo.
+
+ public override string ToString()
+ {
+ return String.Format("TextHandle (vbo): {0} ({1} element(s), vbo id: {2}, ebo id: {3}",
+ Handle, element_count / 6, vbo_id, ebo_id);
+ }
+ }
+
+ #endregion
+}