mirror of
				https://github.com/Ryujinx/Opentk.git
				synced 2025-11-04 08:24:54 +00:00 
			
		
		
		
	Added missing files from working copy.
This commit is contained in:
		
							parent
							
								
									5e449dabd4
								
							
						
					
					
						commit
						18cb4d2432
					
				
							
								
								
									
										201
									
								
								Source/Utilities/Graphics/AlphaTexture2D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								Source/Utilities/Graphics/AlphaTexture2D.cs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,201 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Drawing;
 | 
				
			||||||
 | 
					using System.Drawing.Imaging;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenTK.Graphics
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Encapsulates an OpenGL texture.
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    class AlphaTexture2D : IGraphicsResource
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        #region Fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GraphicsContext context;
 | 
				
			||||||
 | 
					        int id;
 | 
				
			||||||
 | 
					        int width, height;
 | 
				
			||||||
 | 
					        bool disposed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Constructors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Constructs a new Texture.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public AlphaTexture2D(int width, int height)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Width = width;
 | 
				
			||||||
 | 
					            Height = height;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region IGraphicsResource Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GraphicsContext IGraphicsResource.Context { get { return context; } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int IGraphicsResource.Id
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (id == 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    GraphicsContext.Assert();
 | 
				
			||||||
 | 
					                    context = GraphicsContext.CurrentContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    id = GL.GenTexture();
 | 
				
			||||||
 | 
					                    if (id == 0)
 | 
				
			||||||
 | 
					                        throw new GraphicsResourceException(String.Format("Texture creation failed, (Error: {0})", GL.GetError()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Ensure the texture is allocated.
 | 
				
			||||||
 | 
					                    GL.BindTexture(TextureTarget.Texture2D, id);
 | 
				
			||||||
 | 
					                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
 | 
				
			||||||
 | 
					                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
 | 
				
			||||||
 | 
					                    if (GL.SupportsExtension("Version12"))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge);
 | 
				
			||||||
 | 
					                        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Clamp);
 | 
				
			||||||
 | 
					                        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Clamp);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Alpha, Width, Height, 0,
 | 
				
			||||||
 | 
					                        OpenTK.Graphics.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return id;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Public Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region public int Width
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>Gets the width of the texture.</summary>
 | 
				
			||||||
 | 
					        public int Width { get { return width; } private set { width = value; } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region public int Height
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>Gets the height of the texture.</summary>
 | 
				
			||||||
 | 
					        public int Height { get { return height; } private set { height = value; } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region WriteRegion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void WriteRegion(Rectangle source, Rectangle target, int mipLevel, Bitmap bitmap)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (bitmap == null)
 | 
				
			||||||
 | 
					                throw new ArgumentNullException("data");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            GraphicsUnit unit = GraphicsUnit.Pixel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!bitmap.GetBounds(ref unit).Contains(source))
 | 
				
			||||||
 | 
					                throw new InvalidOperationException("The source Rectangle is larger than the Bitmap.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (mipLevel < 0)
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException("mipLevel");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Bind();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BitmapData data = bitmap.LockBits(source, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            GL.PushClientAttrib(ClientAttribMask.ClientPixelStoreBit);
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
 | 
				
			||||||
 | 
					                GL.PixelStore(PixelStoreParameter.UnpackRowLength, bitmap.Width);
 | 
				
			||||||
 | 
					                GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel,
 | 
				
			||||||
 | 
					                    target.Left, target.Top,
 | 
				
			||||||
 | 
					                    target.Width, target.Height,
 | 
				
			||||||
 | 
					                    OpenTK.Graphics.PixelFormat.Rgba,
 | 
				
			||||||
 | 
					                    PixelType.UnsignedByte, data.Scan0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            finally
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                GL.PopClientAttrib();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bitmap.UnlockBits(data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void WriteRegion(TextureRegion2D region, int mipLevel)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (mipLevel < 0)
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException("miplevel");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel,
 | 
				
			||||||
 | 
					                region.Rectangle.X, region.Rectangle.Y,
 | 
				
			||||||
 | 
					                region.Rectangle.Width, region.Rectangle.Height,
 | 
				
			||||||
 | 
					                PixelFormat.Bgra, PixelType.UnsignedByte, region);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region ReadRegion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public TextureRegion2D ReadRegion(Rectangle rect, int mipLevel)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (mipLevel < 0)
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException("miplevel");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            TextureRegion2D<int> region = new TextureRegion2D<int>(rect);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            GL.GetTexImage(TextureTarget.Texture2D, mipLevel, PixelFormat.Bgra, PixelType.UnsignedByte, region.Data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return region;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Bind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Bind()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            GL.BindTexture(TextureTarget.Texture2D, (this as IGraphicsResource).Id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region IDisposable Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Dispose()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Dispose(true);
 | 
				
			||||||
 | 
					            GC.SuppressFinalize(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void Dispose(bool manual)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!disposed)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (manual)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    GL.DeleteTexture(id);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                disposed = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ~AlphaTexture2D()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            GraphicsContext context = (this as IGraphicsResource).Context;
 | 
				
			||||||
 | 
					            if (context != null)
 | 
				
			||||||
 | 
					             (context as IGraphicsContextInternal).RegisterForDisposal(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										268
									
								
								Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,268 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Drawing;
 | 
				
			||||||
 | 
					using System.Drawing.Text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using OpenTK.Graphics.Text;
 | 
				
			||||||
 | 
					using OpenTK.Platform;
 | 
				
			||||||
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenTK.Graphics.Text
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class GdiPlusGlyphRasterizer : IGlyphRasterizer
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        #region Fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Dictionary<TextBlock, TextExtents> block_cache = new Dictionary<TextBlock, TextExtents>();
 | 
				
			||||||
 | 
					        System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(new Bitmap(1, 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges];
 | 
				
			||||||
 | 
					        CharacterRange[] characterRanges = new CharacterRange[GdiPlus.MaxMeasurableCharacterRanges];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TextExtents extents = new TextExtents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check the constructor, too, for additional flags.
 | 
				
			||||||
 | 
					        static readonly StringFormat default_string_format = StringFormat.GenericTypographic;
 | 
				
			||||||
 | 
					        static readonly StringFormat load_glyph_string_format = StringFormat.GenericDefault;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static readonly char[] newline_characters = new char[] { '\n', '\r' };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Constructors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static GdiPlusGlyphRasterizer()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            default_string_format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public GdiPlusGlyphRasterizer()
 | 
				
			||||||
 | 
					        { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region IGlyphRasterizer Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Rasterize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Bitmap Rasterize(Glyph glyph)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            using (Bitmap bmp = new Bitmap((int)(2 * glyph.Font.Size), (int)(2 * glyph.Font.Size)))
 | 
				
			||||||
 | 
					            using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(bmp))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Small sizes look blurry without gridfitting, so turn that on. 
 | 
				
			||||||
 | 
					                if (glyph.Font.Size <= 18.0f)
 | 
				
			||||||
 | 
					                    gfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    gfx.TextRenderingHint = TextRenderingHint.AntiAlias;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                gfx.Clear(Color.Transparent);
 | 
				
			||||||
 | 
					                gfx.DrawString(glyph.Character.ToString(), glyph.Font, Brushes.White, PointF.Empty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Rectangle tight_rect = FindEdges(bmp);
 | 
				
			||||||
 | 
					                Bitmap tight_glyph = bmp.Clone(tight_rect, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 | 
				
			||||||
 | 
					                //new Bitmap(tight_rect.Width, tight_rect.Height);
 | 
				
			||||||
 | 
					                //return bmp.Clone(FindEdges(bmp), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
 | 
				
			||||||
 | 
					                return tight_glyph;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region MeasureText
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //public RectangleF MeasureText(TextBlock block)
 | 
				
			||||||
 | 
					        //{
 | 
				
			||||||
 | 
					        //    return MeasureText(block, ref extents);
 | 
				
			||||||
 | 
					        //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public TextExtents MeasureText(TextBlock block)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // First, check if we have cached this text block. Do not use block_cache.TryGetValue, to avoid thrashing
 | 
				
			||||||
 | 
					            // the user's TextBlockExtents struct.
 | 
				
			||||||
 | 
					            if (block_cache.ContainsKey(block))
 | 
				
			||||||
 | 
					                return block_cache[block];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // If this block is not cached, we have to measure it and place it in the cache.
 | 
				
			||||||
 | 
					            MeasureTextExtents(block, ref extents);
 | 
				
			||||||
 | 
					            if ((block.Options & TextPrinterOptions.NoCache) == 0)
 | 
				
			||||||
 | 
					                block_cache.Add(block, new TextExtents(extents.BoundingBox, extents.GlyphExtents));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return extents;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region MeasureGlyph
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public RectangleF MeasureGlyph(Glyph glyph)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            using (Bitmap bmp = Rasterize(glyph))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return FindEdges(bmp);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Private Members
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region MeasureTextExtents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void MeasureTextExtents(TextBlock block, ref TextExtents extents)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Todo: Parse layout options:
 | 
				
			||||||
 | 
					            StringFormat format = default_string_format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            extents.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            PointF origin = PointF.Empty;
 | 
				
			||||||
 | 
					            SizeF size = SizeF.Empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            IntPtr native_graphics = GdiPlus.GetNativeGraphics(graphics);
 | 
				
			||||||
 | 
					            IntPtr native_font = GdiPlus.GetNativeFont(block.Font);
 | 
				
			||||||
 | 
					            IntPtr native_string_format = GdiPlus.GetNativeStringFormat(format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int height = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // It seems that the mere presence of \n and \r characters
 | 
				
			||||||
 | 
					            // is enough for Mono to botch the layout (even if these
 | 
				
			||||||
 | 
					            // characters are not processed.) We'll need to find a
 | 
				
			||||||
 | 
					            // different way to perform layout on Mono, probably
 | 
				
			||||||
 | 
					            // through Pango.
 | 
				
			||||||
 | 
					            // Todo: This workaround  allocates memory.
 | 
				
			||||||
 | 
					            //if (Configuration.RunningOnMono)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                string[] lines = block.Text.Replace("\r", String.Empty).Split('\n');
 | 
				
			||||||
 | 
					                foreach (string s in lines)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    extents.AddRange(MeasureGlyphExtents(
 | 
				
			||||||
 | 
					                        s, height, 0, s.Length, block.LayoutRectangle,
 | 
				
			||||||
 | 
					                        native_graphics, native_font, native_string_format));
 | 
				
			||||||
 | 
					                    height += block.Font.Height;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            extents.BoundingBox = new RectangleF(extents[0].X, extents[0].Y, extents[extents.Count - 1].Right, extents[extents.Count - 1].Bottom);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region MeasureGlyphExtents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Gets the bounds of each character in a line of text.
 | 
				
			||||||
 | 
					        // The line is processed in blocks of 32 characters (GdiPlus.MaxMeasurableCharacterRanges).
 | 
				
			||||||
 | 
					        IEnumerable<RectangleF> MeasureGlyphExtents(string text, int height, int line_start, int line_length,
 | 
				
			||||||
 | 
					            RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            RectangleF rect = new RectangleF();
 | 
				
			||||||
 | 
					            int line_end = line_start + line_length;
 | 
				
			||||||
 | 
					            while (line_start < line_end)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                //if (text[line_start] == '\n' || text[line_start] == '\r')
 | 
				
			||||||
 | 
					                //{
 | 
				
			||||||
 | 
					                //    line_start++;
 | 
				
			||||||
 | 
					                //    continue;
 | 
				
			||||||
 | 
					                //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                int num_characters = (line_end - line_start) > GdiPlus.MaxMeasurableCharacterRanges ?
 | 
				
			||||||
 | 
					                    GdiPlus.MaxMeasurableCharacterRanges :
 | 
				
			||||||
 | 
					                    line_end - line_start;
 | 
				
			||||||
 | 
					                int status = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (int i = 0; i < num_characters; i++)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    characterRanges[i] = new CharacterRange(line_start + i, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    IntPtr region;
 | 
				
			||||||
 | 
					                    status = GdiPlus.CreateRegion(out region);
 | 
				
			||||||
 | 
					                    regions[i] = region;
 | 
				
			||||||
 | 
					                    Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                status = GdiPlus.SetStringFormatMeasurableCharacterRanges(native_string_format, num_characters, characterRanges);
 | 
				
			||||||
 | 
					                Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                status = GdiPlus.MeasureCharacterRanges(native_graphics, text, text.Length,
 | 
				
			||||||
 | 
					                                                native_font, ref layoutRect, native_string_format, num_characters, regions);
 | 
				
			||||||
 | 
					                Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (int i = 0; i < num_characters; i++)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    GdiPlus.GetRegionBounds(regions[i], native_graphics, ref rect);
 | 
				
			||||||
 | 
					                    Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
 | 
				
			||||||
 | 
					                    GdiPlus.DeleteRegion(regions[i]);
 | 
				
			||||||
 | 
					                    Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    rect.Y += height;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    yield return rect;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                line_start += num_characters;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region FindEdges
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Rectangle FindEdges(Bitmap bmp)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return Rectangle.FromLTRB(
 | 
				
			||||||
 | 
					                FindLeftEdge(bmp),
 | 
				
			||||||
 | 
					                FindTopEdge(bmp),
 | 
				
			||||||
 | 
					                FindRightEdge(bmp),
 | 
				
			||||||
 | 
					                FindBottomEdge(bmp));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Find[Left|Right|Top|Bottom]Edge
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Iterates through the bmp, and returns the first row or line that contains a non-transparent pixels.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int FindLeftEdge(Bitmap bmp)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            for (int x = 0; x < bmp.Width; x++)
 | 
				
			||||||
 | 
					                for (int y = 0; y < bmp.Height; y++)
 | 
				
			||||||
 | 
					                    if (bmp.GetPixel(x, y).A != 0)
 | 
				
			||||||
 | 
					                        return x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return bmp.Width;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int FindRightEdge(Bitmap bmp)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            for (int x = bmp.Width - 1; x >= 0; x--)
 | 
				
			||||||
 | 
					                for (int y = 0; y < bmp.Height; y++)
 | 
				
			||||||
 | 
					                    if (bmp.GetPixel(x, y).A != 0)
 | 
				
			||||||
 | 
					                        return x + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int FindTopEdge(Bitmap bmp)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Don't trim the top edge, because the layout engine expects it to be 0.
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int FindBottomEdge(Bitmap bmp)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            for (int y = bmp.Height - 1; y >= 0; y--)
 | 
				
			||||||
 | 
					                for (int x = 0; x < bmp.Width; x++)
 | 
				
			||||||
 | 
					                    if (bmp.GetPixel(x, y).A != 0)
 | 
				
			||||||
 | 
					                        return y + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in a new issue