diff --git a/Source/Examples/Tutorial/Fonts.cs b/Source/Examples/Tutorial/Fonts.cs index 10964284..62f602c7 100644 --- a/Source/Examples/Tutorial/Fonts.cs +++ b/Source/Examples/Tutorial/Fonts.cs @@ -165,12 +165,7 @@ namespace Examples.Tutorial { GL.Clear(ClearBufferMask.ColorBufferBit); - GL.MatrixMode(MatrixMode.Projection); - GL.LoadIdentity(); - GL.Ortho(0.0, Width, Height, 0.0, 0.0, 1.0); - - GL.MatrixMode(MatrixMode.Modelview); - GL.LoadIdentity(); + printer.Begin(); // Print using the first font. for (int i = 0; i < handles.Length / 2; i++) @@ -190,6 +185,8 @@ namespace Examples.Tutorial GL.Translate(0, fonts[i].Height, 0); } + printer.End(); + SwapBuffers(); } diff --git a/Source/Examples/Tutorial/Text.cs b/Source/Examples/Tutorial/Text.cs index 4357559b..a78063c3 100644 --- a/Source/Examples/Tutorial/Text.cs +++ b/Source/Examples/Tutorial/Text.cs @@ -120,20 +120,18 @@ namespace Examples.Tutorial else if (scroll_speed < 0.0f && current_position < warparound_position) current_position = initial_position; - // Prepare to draw text. We want pixel perfect precision, so we setup a 2D mode, - // with size equal to the window (in pixels). - // While we could also render text in 3D mode, it would be very hard to get - // pixel-perfect precision. - GL.MatrixMode(MatrixMode.Projection); - GL.LoadIdentity(); - GL.Ortho(0.0, Width, Height, 0.0, 0.0, 1.0); - - GL.MatrixMode(MatrixMode.Modelview); - GL.LoadIdentity(); + // TextPrinter.Begin() sets up a 2d orthographic projection, with the x axis + // moving from 0 to viewport.Width (left to right) and the y axis from + // 0 to viewport.Height (top to bottom). This is the typical coordinate system + // used in 2d graphics, and is necessary for achieving pixel-perfect glyph rendering. + // TextPrinter.End() restores your previous projection/modelview matrices. + text.Begin(); GL.Translate(0.0f, current_position, 0.0f); text.Draw(poem_handle); + text.End(); + SwapBuffers(); } diff --git a/Source/OpenTK/Fonts/ITextPrinter.cs b/Source/OpenTK/Fonts/ITextPrinter.cs index 3ee3b290..aaf74e62 100644 --- a/Source/OpenTK/Fonts/ITextPrinter.cs +++ b/Source/OpenTK/Fonts/ITextPrinter.cs @@ -21,5 +21,7 @@ namespace OpenTK.Fonts void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp, StringAlignment alignment); void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp, StringAlignment alignment, bool rightToLeft); void Draw(TextHandle handle); + void Begin(); + void End(); } } diff --git a/Source/OpenTK/Fonts/TextPrinter.cs b/Source/OpenTK/Fonts/TextPrinter.cs index a8a9b6ca..238892ca 100644 --- a/Source/OpenTK/Fonts/TextPrinter.cs +++ b/Source/OpenTK/Fonts/TextPrinter.cs @@ -27,6 +27,7 @@ namespace OpenTK.Fonts //static char[] split_chars = new char[] { ' ', '\n', '\t', ',', '.', '/', '?', '!', ';', '\\', '-', '+', '*', '=' }; static bool functionality_checked = false; static ITextPrinterImplementation printer; + float[] viewport = new float[6]; #region --- Constructor --- @@ -62,21 +63,72 @@ namespace OpenTK.Fonts #region --- ITextPrinter Members --- + #region public void Prepare(string text, TextureFont font, out TextHandle handle) + + /// + /// Prepares text for drawing. + /// + /// The string to draw. + /// The font to use for drawing. + /// The handle to the cached text. Use this to draw the text with the Draw() function. + /// public void Prepare(string text, TextureFont font, out TextHandle handle) { this.Prepare(text, font, out handle, 0, false, StringAlignment.Near, false); } + #endregion + + #region public void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp) + + /// + /// Prepares text for drawing. + /// + /// The string to draw. + /// The font to use for drawing. + /// The handle to the cached text. Use this to draw the text with the Draw() function. + /// Not implemented. + /// Not implemented. + /// public void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp) { this.Prepare(text, font, out handle, width, wordWarp, StringAlignment.Near, false); } + #endregion + + #region public void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp, StringAlignment alignment) + + /// + /// Prepares text for drawing. + /// + /// The string to draw. + /// The font to use for drawing. + /// The handle to the cached text. Use this to draw the text with the Draw() function. + /// Not implemented. + /// Not implemented. + /// Not implemented. + /// public void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp, StringAlignment alignment) { this.Prepare(text, font, out handle, width, wordWarp, alignment, false); } + #endregion + + #region public void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp, StringAlignment alignment, bool rightToLeft) + + /// + /// Prepares text for drawing. + /// + /// The string to draw. + /// The font to use for drawing. + /// The handle to the cached text. Use this to draw the text with the Draw() function. + /// Not implemented. + /// Not implemented. + /// Not implemented. + /// Not implemented. + /// public void Prepare(string text, TextureFont font, out TextHandle handle, float width, bool wordWarp, StringAlignment alignment, bool rightToLeft) { if (!functionality_checked) @@ -88,6 +140,9 @@ namespace OpenTK.Fonts if (text.Length > 8192) throw new ArgumentOutOfRangeException("text", text.Length, "Text length must be between 1 and 8192 characters"); + if (wordWarp || rightToLeft || alignment != StringAlignment.Near) + throw new NotImplementedException(); + Vector2[] vertices = new Vector2[8 * text.Length]; // Interleaved, vertex, texcoord, vertex, etc... ushort[] indices = new ushort[6 * text.Length]; float x_pos = 0, y_pos = 0; @@ -167,8 +222,49 @@ namespace OpenTK.Fonts handle.font = font; } + #endregion + + #region public void Draw(TextHandle handle) + + /// + /// Draws the cached text referred to by the TextHandle. + /// + /// The TextHandle to the cached text. public void Draw(TextHandle handle) { + GL.BindTexture(TextureTarget.Texture2d, handle.font.Texture); + + printer.Draw(handle); + } + + #endregion + + #region public void Draw(string text) + + #endregion + + #region public void Begin() + + /// + /// Sets up OpenGL state for drawing text. + /// + public void Begin() + { + GL.PushMatrix(); + + GL.GetFloat(GetPName.Viewport, viewport); + + // Prepare to draw text. We want pixel perfect precision, so we setup a 2D mode, + // with size equal to the window (in pixels). + // While we could also render text in 3D mode, it would be very hard to get + // pixel-perfect precision. + GL.MatrixMode(MatrixMode.Projection); + GL.LoadIdentity(); + GL.Ortho(viewport[0], viewport[2], viewport[3], viewport[1], 0.0, 1.0); + + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + GL.PushAttrib(AttribMask.TextureBit); GL.PushAttrib(AttribMask.EnableBit); @@ -177,15 +273,24 @@ namespace OpenTK.Fonts GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Disable(EnableCap.DepthTest); - - GL.BindTexture(TextureTarget.Texture2d, handle.font.Texture); - - printer.Draw(handle); - - GL.PopAttrib(); - GL.PopAttrib(); } #endregion + + #region public void End() + + /// + /// Restores OpenGL state. + /// + public void End() + { + GL.PopAttrib(); + GL.PopAttrib(); + GL.PopMatrix(); + } + + #endregion + + #endregion } }