From 263f33ca5b229ca6e415caede4b203d18c2c1425 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Tue, 18 Jan 2011 11:15:49 +0000 Subject: [PATCH] Added new TextRendering sample. --- Source/Examples/OpenGL/1.x/TextRendering.cs | 287 +++++++++++++++++++ Source/Examples/OpenGL/1.x/TextRendering.rtf | Bin 0 -> 823 bytes Source/Examples/OpenTK.Examples.csproj | 4 +- 3 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 Source/Examples/OpenGL/1.x/TextRendering.cs create mode 100644 Source/Examples/OpenGL/1.x/TextRendering.rtf diff --git a/Source/Examples/OpenGL/1.x/TextRendering.cs b/Source/Examples/OpenGL/1.x/TextRendering.cs new file mode 100644 index 00000000..47e525e1 --- /dev/null +++ b/Source/Examples/OpenGL/1.x/TextRendering.cs @@ -0,0 +1,287 @@ +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2011 the Open Toolkit library. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; + +namespace Examples.Tutorial +{ + [Example("Text Rendering (2D)", ExampleCategory.OpenGL, "1.x", Documentation = "TextRendering")] + class TextRendering : GameWindow + { + TextRenderer renderer; + Font serif = new Font(FontFamily.GenericSerif, 24); + Font sans = new Font(FontFamily.GenericSansSerif, 24); + Font mono = new Font(FontFamily.GenericMonospace, 24); + + /// + /// Uses System.Drawing for 2d text rendering. + /// + public class TextRenderer : IDisposable + { + Bitmap bmp; + Graphics gfx; + int texture; + Rectangle dirty_region; + bool disposed; + + #region Constructors + + /// + /// Constructs a new instance. + /// + /// The width of the backing store in pixels. + /// The height of the backing store in pixels. + public TextRenderer(int width, int height) + { + if (width <= 0) + throw new ArgumentOutOfRangeException("width"); + if (height <= 0) + throw new ArgumentOutOfRangeException("height "); + if (GraphicsContext.CurrentContext == null) + throw new InvalidOperationException("No GraphicsContext is current on the calling thread."); + + bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + gfx = Graphics.FromImage(bmp); + gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; + + texture = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, texture); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, + PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); + } + + #endregion + + #region Public Members + + /// + /// Clears the backing store to the specified color. + /// + /// A . + public void Clear(Color color) + { + gfx.Clear(color); + dirty_region = new Rectangle(0, 0, bmp.Width, bmp.Height); + } + + /// + /// Draws the specified string to the backing store. + /// + /// The to draw. + /// The that will be used. + /// The that will be used. + /// The location of the text on the backing store, in 2d pixel coordinates. + /// The origin (0, 0) lies at the top-left corner of the backing store. + public void DrawString(string text, Font font, Brush brush, PointF point) + { + gfx.DrawString(text, font, brush, point); + + SizeF size = gfx.MeasureString(text, font); + dirty_region = Rectangle.Round(RectangleF.Union(dirty_region, new RectangleF(point, size))); + dirty_region = Rectangle.Intersect(dirty_region, new Rectangle(0, 0, bmp.Width, bmp.Height)); + } + + /// + /// Gets a that represents an OpenGL 2d texture handle. + /// The texture contains a copy of the backing store. Bind this texture to TextureTarget.Texture2d + /// in order to render the drawn text on screen. + /// + public int Texture + { + get + { + UploadBitmap(); + return texture; + } + } + + #endregion + + #region Private Members + + // Uploads the dirty regions of the backing store to the OpenGL texture. + void UploadBitmap() + { + if (dirty_region != RectangleF.Empty) + { + System.Drawing.Imaging.BitmapData data = bmp.LockBits(dirty_region, + System.Drawing.Imaging.ImageLockMode.ReadOnly, + System.Drawing.Imaging.PixelFormat.Format32bppArgb); + + GL.BindTexture(TextureTarget.Texture2D, texture); + GL.TexSubImage2D(TextureTarget.Texture2D, 0, + dirty_region.X, dirty_region.Y, dirty_region.Width, dirty_region.Height, + PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0); + + bmp.UnlockBits(data); + + dirty_region = Rectangle.Empty; + } + } + + #endregion + + #region IDisposable Members + + void Dispose(bool manual) + { + if (!disposed) + { + if (manual) + { + bmp.Dispose(); + gfx.Dispose(); + if (GraphicsContext.CurrentContext != null) + GL.DeleteTexture(texture); + } + + disposed = true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + ~TextRenderer() + { + Console.WriteLine("[Warning] Resource leaked: {0}.", typeof(TextRenderer)); + } + + #endregion + } + + #region Constructor + + public TextRendering() + : base(800, 600) + { + } + + #endregion + + #region OnLoad + + protected override void OnLoad(EventArgs e) + { + renderer = new TextRenderer(Width, Height); + PointF position = PointF.Empty; + + renderer.Clear(Color.MidnightBlue); + renderer.DrawString("The quick brown fox jumps over the lazy dog", serif, Brushes.White, position); + position.Y += serif.Height; + renderer.DrawString("The quick brown fox jumps over the lazy dog", sans, Brushes.White, position); + position.Y += sans.Height; + renderer.DrawString("The quick brown fox jumps over the lazy dog", mono, Brushes.White, position); + position.Y += mono.Height; + } + + #endregion + + #region OnUnload + + protected override void OnUnload(EventArgs e) + { + renderer.Dispose(); + } + + #endregion + + #region OnResize + + protected override void OnResize(EventArgs e) + { + GL.Viewport(ClientRectangle); + + GL.MatrixMode(MatrixMode.Projection); + GL.LoadIdentity(); + GL.Ortho(-1.0, 1.0, -1.0, 1.0, 0.0, 4.0); + } + + #endregion + + #region OnUpdateFrame + + protected override void OnUpdateFrame(FrameEventArgs e) + { + if (Keyboard[OpenTK.Input.Key.Escape]) + { + this.Exit(); + } + } + + #endregion + + #region OnRenderFrame + + protected override void OnRenderFrame(FrameEventArgs e) + { + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + + GL.Enable(EnableCap.Texture2D); + GL.BindTexture(TextureTarget.Texture2D, renderer.Texture); + GL.Begin(BeginMode.Quads); + + GL.TexCoord2(0.0f, 1.0f); GL.Vertex2(-1f, -1f); + GL.TexCoord2(1.0f, 1.0f); GL.Vertex2(1f, -1f); + GL.TexCoord2(1.0f, 0.0f); GL.Vertex2(1f, 1f); + GL.TexCoord2(0.0f, 0.0f); GL.Vertex2(-1f, 1f); + + GL.End(); + + SwapBuffers(); + } + + #endregion + + #region Main + + public static void Main() + { + using (TextRendering example = new TextRendering()) + { + Utilities.SetWindowTitle(example); + example.Run(30.0); + } + } + + #endregion + } +} diff --git a/Source/Examples/OpenGL/1.x/TextRendering.rtf b/Source/Examples/OpenGL/1.x/TextRendering.rtf new file mode 100644 index 0000000000000000000000000000000000000000..ae3ed7c3904f6c05f1c1e296f7d291492fb608a4 GIT binary patch literal 823 zcmZva(QDf<5XSdh=>Kq!+d53_G-D%A-8xEPV`Iz9Krga%inYp;kWNX{kpI1BI~z?H z7-6jQ@B8k%+lxe|7Sd-s9xATuW-%8UjhXF*37)8R{4x{9TPKX_WXec0xJg#J<>7F7 zu@@@1khl((BB8F|&&4_+`lc4GE7;V_vFfc@qsJsEB>0vMp|%8z>bkBPeipNj%Y)ch z+&);ZuSHR{h%#xR*q@VrUC-uo(F&8B4{+}(1zi-`;6=;ca?=demlxBy>THHA`{)of z_Q7XjUCbao$QV({Wc5`OJ6VPD-Qxg9>ezPr7@dQ-jR{|*Hd zvs8#XpblZhl%FF66DTKh9`I6Y$R$P&2Ml+8ro|PzP!h18Kd9(LVfBA#$=t-5KgMXb zI?=5kbk9nvPnLQaD;TJXXNsOO1T$Kn?m#Al5?zoQITU7i_#V;UeI2=lZ#(HV=SiKU zvH2FE4aI9N)yD*P3ND!3W*50PwdpX4yRccX(d9UfgmlQ4ITbMnc$ z9c(*ZoegKpE5rAb?hxs}$(^M4cTYZZuPL~EoZZQ${9uI)U$O$mC}-8fXhyk^xv@eN P{E!1a+SAGKF28yPAZ{Sy literal 0 HcmV?d00001 diff --git a/Source/Examples/OpenTK.Examples.csproj b/Source/Examples/OpenTK.Examples.csproj index 789042bb..b52793d5 100644 --- a/Source/Examples/OpenTK.Examples.csproj +++ b/Source/Examples/OpenTK.Examples.csproj @@ -1,4 +1,4 @@ - + Local @@ -151,6 +151,7 @@ Code + Code @@ -553,6 +554,7 @@ +