mirror of
				https://github.com/Ryujinx/Opentk.git
				synced 2025-11-04 15:55:00 +00:00 
			
		
		
		
	Now uses Alpha texture. Corrected issue with PixelInternalFormat enum not being used. Added preliminary layout code.
This commit is contained in:
		
							parent
							
								
									339ae77c29
								
							
						
					
					
						commit
						22c1e5011d
					
				| 
						 | 
				
			
			@ -1,4 +1,10 @@
 | 
			
		|||
using System;
 | 
			
		||||
#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.Drawing;
 | 
			
		||||
| 
						 | 
				
			
			@ -11,21 +17,26 @@ using OpenTK.Platform;
 | 
			
		|||
 | 
			
		||||
namespace OpenTK.Fonts
 | 
			
		||||
{
 | 
			
		||||
    public class TextureFont : IDisposable
 | 
			
		||||
    public class TextureFont : IFont
 | 
			
		||||
    {
 | 
			
		||||
        Font font;
 | 
			
		||||
        Dictionary<char, int> loaded_glyphs = new Dictionary<char, int>(36);
 | 
			
		||||
        Graphics gfx = Graphics.FromImage(new Bitmap(1, 1));
 | 
			
		||||
        //class BBox { public int X, Y, Width, Height; }
 | 
			
		||||
 | 
			
		||||
        Font font;
 | 
			
		||||
        //Dictionary<char, int> loaded_glyphs = new Dictionary<char, int>(36);
 | 
			
		||||
        Dictionary<char, RectangleF> loaded_glyphs = new Dictionary<char, RectangleF>(64);
 | 
			
		||||
 | 
			
		||||
        Graphics gfx = Graphics.FromImage(new Bitmap(1, 1));
 | 
			
		||||
        static int texture;
 | 
			
		||||
        static TexturePacker<Glyph> pack;
 | 
			
		||||
        static int texture_width, texture_height;
 | 
			
		||||
        float[] viewport = new float[6];
 | 
			
		||||
 | 
			
		||||
        #region --- Constructor ---
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Constructs a new TextureFont object, using the specified System.Drawing.Font.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="font"></param>
 | 
			
		||||
        /// <param name="font">The System.Drawing.Font to use.</param>
 | 
			
		||||
        public TextureFont(Font font)
 | 
			
		||||
        {
 | 
			
		||||
            if (font == null)
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +45,41 @@ namespace OpenTK.Fonts
 | 
			
		|||
            this.font = font;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region private void PrepareTexturePacker()
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Calculates the optimal size for the font texture and TexturePacker, and creates both.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void PrepareTexturePacker()
 | 
			
		||||
        {
 | 
			
		||||
            // Calculate the size of the texture packer. We want a power-of-two size
 | 
			
		||||
            // that is less than 1024 (supported in Geforce256-era cards), but large
 | 
			
		||||
            // enough to hold at least 256 (16*16) font glyphs.
 | 
			
		||||
            // TODO: Find the actual card limits, maybe?
 | 
			
		||||
            int size = (int)(font.Size * 16);
 | 
			
		||||
            size = (int)System.Math.Pow(2.0, System.Math.Ceiling(System.Math.Log((double)size, 2.0)));
 | 
			
		||||
            if (size > 1024)
 | 
			
		||||
                size = 1024;
 | 
			
		||||
 | 
			
		||||
            texture_width = size;
 | 
			
		||||
            texture_height = size;
 | 
			
		||||
            pack = new TexturePacker<Glyph>(texture_width, texture_height);
 | 
			
		||||
 | 
			
		||||
            GL.GenTextures(1, out texture);
 | 
			
		||||
            GL.BindTexture(GL.Enums.TextureTarget.TEXTURE_2D, texture);
 | 
			
		||||
            GL.TexParameter(GL.Enums.TextureTarget.TEXTURE_2D, GL.Enums.TextureParameterName.TEXTURE_MIN_FILTER, (int)GL.Enums.All.LINEAR);
 | 
			
		||||
            GL.TexParameter(GL.Enums.TextureTarget.TEXTURE_2D, GL.Enums.TextureParameterName.TEXTURE_MAG_FILTER, (int)GL.Enums.All.LINEAR);
 | 
			
		||||
 | 
			
		||||
            GL.TexImage2D(GL.Enums.TextureTarget.TEXTURE_2D, 0, GL.Enums.PixelInternalFormat.ALPHA, texture_width, texture_height, 0,
 | 
			
		||||
                GL.Enums.PixelFormat.RGBA, GL.Enums.PixelType.UNSIGNED_BYTE, IntPtr.Zero);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region public void LoadGlyphs(string glyphs)
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Prepares the specified glyphs for rendering.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +93,11 @@ namespace OpenTK.Fonts
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private int LoadGlyph(char c)
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region private RectangleF LoadGlyph(char c)
 | 
			
		||||
 | 
			
		||||
        private RectangleF LoadGlyph(char c)
 | 
			
		||||
        {
 | 
			
		||||
            if (pack == null)
 | 
			
		||||
                PrepareTexturePacker();
 | 
			
		||||
| 
						 | 
				
			
			@ -55,21 +105,54 @@ namespace OpenTK.Fonts
 | 
			
		|||
            Glyph g = new Glyph(c, font);
 | 
			
		||||
            Rectangle rect = pack.Add(g);
 | 
			
		||||
 | 
			
		||||
            using (Bitmap bmp = new Bitmap(g.Width, g.Height, PixelFormat.Format32bppArgb))
 | 
			
		||||
            using (Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb))
 | 
			
		||||
            using (Graphics gfx = Graphics.FromImage(bmp))
 | 
			
		||||
            {
 | 
			
		||||
                // Upload texture and create Display List:
 | 
			
		||||
                GL.BindTexture(GL.Enums.TextureTarget.TEXTURE_2D, texture);
 | 
			
		||||
 | 
			
		||||
                gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
 | 
			
		||||
                //gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
 | 
			
		||||
                //gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
 | 
			
		||||
                gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
 | 
			
		||||
 | 
			
		||||
                gfx.Clear(Color.Transparent);
 | 
			
		||||
                gfx.DrawString(g.Character.ToString(), g.Font, Brushes.White, 0.0f, 0.0f);
 | 
			
		||||
                BitmapData data = bmp.LockBits(new Rectangle(0, 0, g.Width, g.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
 | 
			
		||||
 | 
			
		||||
                BitmapData bmp_data = bmp.LockBits(new Rectangle(0, 0, rect.Width, rect.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
 | 
			
		||||
                GL.TexSubImage2D(GL.Enums.TextureTarget.TEXTURE_2D, 0, rect.Left, rect.Top, rect.Width, rect.Height,
 | 
			
		||||
                    GL.Enums.PixelFormat.RGBA, GL.Enums.PixelType.UNSIGNED_BYTE, data.Scan0);
 | 
			
		||||
                bmp.UnlockBits(data);
 | 
			
		||||
                    GL.Enums.PixelFormat.RGBA, GL.Enums.PixelType.UNSIGNED_BYTE, bmp_data.Scan0);
 | 
			
		||||
                bmp.UnlockBits(bmp_data);
 | 
			
		||||
 | 
			
		||||
                RectangleF f_rect = RectangleF.FromLTRB(
 | 
			
		||||
                    rect.Left / (float)texture_width,
 | 
			
		||||
                    rect.Top / (float)texture_height,
 | 
			
		||||
                    rect.Right / (float)texture_width,
 | 
			
		||||
                    rect.Bottom / (float)texture_height);
 | 
			
		||||
                
 | 
			
		||||
                loaded_glyphs.Add(g.Character, f_rect);
 | 
			
		||||
                
 | 
			
		||||
                return f_rect;
 | 
			
		||||
 | 
			
		||||
                /*
 | 
			
		||||
                byte[] data = new byte[rect.Width * rect.Height * 4];
 | 
			
		||||
                int i = 0;
 | 
			
		||||
                for (int y = 0; y < rect.Height - 1; y++)
 | 
			
		||||
                {
 | 
			
		||||
                    for (int x = 0; x < rect.Width - 1; x++)
 | 
			
		||||
                    {
 | 
			
		||||
                        data[i++] = bmp.GetPixel(x, y).R;
 | 
			
		||||
                        data[i++] = bmp.GetPixel(x, y).G;
 | 
			
		||||
                        data[i++] = bmp.GetPixel(x, y).B;
 | 
			
		||||
                        data[i++] = bmp.GetPixel(x, y).A;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                unsafe
 | 
			
		||||
                {
 | 
			
		||||
                    fixed (byte* data_ptr = data)
 | 
			
		||||
                        GL.TexSubImage2D(GL.Enums.TextureTarget.TEXTURE_2D, 0, rect.Left, rect.Top, rect.Width, rect.Height,
 | 
			
		||||
                            GL.Enums.PixelFormat.RGBA, GL.Enums.PixelType.UNSIGNED_BYTE, (IntPtr)data_ptr);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                float left = rect.Left / (float)texture_width;
 | 
			
		||||
                float bottom = rect.Bottom / (float)texture_height;
 | 
			
		||||
| 
						 | 
				
			
			@ -77,12 +160,13 @@ namespace OpenTK.Fonts
 | 
			
		|||
                float top = rect.Top / (float)texture_height;
 | 
			
		||||
                float width = rect.Right - rect.Left;
 | 
			
		||||
                float height = rect.Bottom - rect.Top;
 | 
			
		||||
 | 
			
		||||
                */
 | 
			
		||||
                /*
 | 
			
		||||
                int list = GL.GenLists(1);
 | 
			
		||||
                GL.NewList(list, GL.Enums.ListMode.COMPILE);
 | 
			
		||||
 | 
			
		||||
                GL.Enable(GL.Enums.EnableCap.BLEND);
 | 
			
		||||
                GL.BlendFunc(GL.Enums.BlendingFactorSrc.ONE, GL.Enums.BlendingFactorDest.ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
                GL.BlendFunc(GL.Enums.BlendingFactorSrc.SRC_ALPHA, GL.Enums.BlendingFactorDest.ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
 | 
			
		||||
                GL.Begin(GL.Enums.BeginMode.QUADS);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,36 +193,71 @@ namespace OpenTK.Fonts
 | 
			
		|||
                loaded_glyphs.Add(g.Character, list);
 | 
			
		||||
 | 
			
		||||
                return list;
 | 
			
		||||
                */
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        public void Draw()
 | 
			
		||||
        {
 | 
			
		||||
            ILayoutProvider l = new DefaultLayoutProvider();
 | 
			
		||||
            l.PerformLayout("ato e -et uq39tu, /q3t.q/t.q3t q     34t34qwt .", this,
 | 
			
		||||
                new RectangleF(9.0f, 9.0f, 300.0f, 100.0f), StringAlignment.Near, false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region 
 | 
			
		||||
        
 | 
			
		||||
        public bool GlyphData(char glyph, ref RectangleF textureRectangle, out float width, out float height, out int texture)
 | 
			
		||||
        {
 | 
			
		||||
            if (loaded_glyphs.TryGetValue(glyph, out textureRectangle))
 | 
			
		||||
            {
 | 
			
		||||
                width = textureRectangle.Width * texture_width;
 | 
			
		||||
                height = textureRectangle.Height * texture_height;
 | 
			
		||||
                texture = TextureFont.texture;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            width = height = texture = 0;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region public RectangleF FindRectangle(char c)
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Calculates the optimal size for the font texture and TexturePacker, and creates both.
 | 
			
		||||
        /// Looks up the specified glyph and returns it's bounding System.Drawing.Rectangle in the font texture.
 | 
			
		||||
        /// This function will add the glyph to the texture font, if it hasn't been previoulsy loaded through LoadGlyphs().
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void PrepareTexturePacker()
 | 
			
		||||
        /// <param name="c">The character representing the glyph.</param>
 | 
			
		||||
        /// <returns>The System.Drawing.Rectangle that represents the glyph's bounding box in the font texture.</returns>
 | 
			
		||||
        /// <seealso cref="LoadGlyphs"/>
 | 
			
		||||
        public RectangleF FindRectangle(char c)
 | 
			
		||||
        {
 | 
			
		||||
            // Calculate the size of the texture packer. We want a power-of-two size
 | 
			
		||||
            // that is less than 1024 (supported in Geforce256-era cards), but large
 | 
			
		||||
            // enough to hold at least 256 (16*16) font glyphs.
 | 
			
		||||
            int size = (int)(font.Size * 16);
 | 
			
		||||
            size = (int)System.Math.Pow(2.0, System.Math.Ceiling(System.Math.Log((double)size, 2.0)));
 | 
			
		||||
            if (size > 1024)
 | 
			
		||||
                size = 1024;
 | 
			
		||||
 | 
			
		||||
            texture_width = size;
 | 
			
		||||
            texture_height = size;
 | 
			
		||||
            pack = new TexturePacker<Glyph>(texture_width, texture_height);
 | 
			
		||||
 | 
			
		||||
            GL.GenTextures(1, out texture);
 | 
			
		||||
            GL.BindTexture(GL.Enums.TextureTarget.TEXTURE_2D, texture);
 | 
			
		||||
            GL.TexParameter(GL.Enums.TextureTarget.TEXTURE_2D, GL.Enums.TextureParameterName.TEXTURE_MIN_FILTER, (int)GL.Enums.All.LINEAR);
 | 
			
		||||
            GL.TexParameter(GL.Enums.TextureTarget.TEXTURE_2D, GL.Enums.TextureParameterName.TEXTURE_MAG_FILTER, (int)GL.Enums.All.NEAREST);
 | 
			
		||||
 | 
			
		||||
            byte[] data = new byte[texture_height * texture_width * 4];
 | 
			
		||||
            GL.TexImage2D(GL.Enums.TextureTarget.TEXTURE_2D, 0, 4, texture_width, texture_height, 0,
 | 
			
		||||
                GL.Enums.PixelFormat.RGBA, GL.Enums.PixelType.UNSIGNED_BYTE, data);
 | 
			
		||||
            RectangleF rect;
 | 
			
		||||
            return loaded_glyphs.TryGetValue(c, out rect) ? rect : LoadGlyph(c);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region public int FindTexture(char c)
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns the handle to the OpenGL texture where the specified glyph is located or zero, if the glyph has not been loaded.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="c">The character that corresponds to the glyph.</param>
 | 
			
		||||
        /// <returns>A handle to the OpenGL texture, or zero.</returns>
 | 
			
		||||
        public int FindTexture(char c)
 | 
			
		||||
        {
 | 
			
		||||
            if (loaded_glyphs.ContainsKey(c))
 | 
			
		||||
                return texture;
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region public void Print(char c)
 | 
			
		||||
#if false
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Prints a glyph.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +278,8 @@ namespace OpenTK.Fonts
 | 
			
		|||
        /// <seealso cref="PrintFast"/>
 | 
			
		||||
        public void Print(char c)
 | 
			
		||||
        {
 | 
			
		||||
            GL.BindTexture(GL.Enums.TextureTarget.TEXTURE_2D, texture);
 | 
			
		||||
 | 
			
		||||
            int list;
 | 
			
		||||
            if (loaded_glyphs.TryGetValue(c, out list))
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +290,11 @@ namespace OpenTK.Fonts
 | 
			
		|||
                GL.CallList(LoadGlyph(c));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region public void PrintFast(char c)
 | 
			
		||||
#if false
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Prints a previously loaded glyph.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -184,29 +309,39 @@ namespace OpenTK.Fonts
 | 
			
		|||
        {
 | 
			
		||||
            GL.CallList(loaded_glyphs[c]);
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region public float Height
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a float indicating the default line spacing of this font.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public float LineSpacing
 | 
			
		||||
        public float Height
 | 
			
		||||
        {
 | 
			
		||||
            get { return font.Height; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region public float MeasureString(string str)
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Measures the width of the specified string.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="str"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public float MeasureWidth(string str)
 | 
			
		||||
        public SizeF MeasureString(string str)
 | 
			
		||||
        {
 | 
			
		||||
            float distance = gfx.MeasureString(str, font, 16384, StringFormat.GenericTypographic).Width;
 | 
			
		||||
            if (distance == 0)
 | 
			
		||||
                distance = font.SizeInPoints * 0.5f;
 | 
			
		||||
            return distance;
 | 
			
		||||
            SizeF size = gfx.MeasureString(str, font, 16384, StringFormat.GenericTypographic);
 | 
			
		||||
            if (size.Width == 0)
 | 
			
		||||
                size.Width = font.SizeInPoints * 0.5f;
 | 
			
		||||
            return size;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region IDisposable Members
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region --- IDisposable Members ---
 | 
			
		||||
 | 
			
		||||
        bool disposed;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue