From a868c4b4e8d93904968bf965e96fa1efd59d30bf Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Wed, 26 Nov 2008 15:35:15 +0000 Subject: [PATCH] Remove exceptions from the typical path (significant speed increase). --- Source/Utilities/Graphics/Text/GlyphCache.cs | 28 +++--- Source/Utilities/Graphics/Text/GlyphPacker.cs | 91 +++++++++++++------ 2 files changed, 74 insertions(+), 45 deletions(-) diff --git a/Source/Utilities/Graphics/Text/GlyphCache.cs b/Source/Utilities/Graphics/Text/GlyphCache.cs index 1b943110..fa99e041 100644 --- a/Source/Utilities/Graphics/Text/GlyphCache.cs +++ b/Source/Utilities/Graphics/Text/GlyphCache.cs @@ -37,7 +37,7 @@ namespace OpenTK.Graphics.Text IGlyphRasterizer rasterizer; List sheets = new List(); - Bitmap bmp = new Bitmap(256, 256); + Bitmap bmp = new Bitmap(32, 32); Dictionary cached_glyphs = new Dictionary(); @@ -64,24 +64,19 @@ namespace OpenTK.Graphics.Text using (Bitmap bmp = rasterizer.Rasterize(glyph)) { + Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); foreach (GlyphSheet sheet in sheets) { - try - { - InsertGlyph(glyph, bmp, sheet); - inserted = true; - break; - } - catch (TexturePackerFullException) - { - } + inserted = InsertGlyph(glyph, bmp, rect, sheet); + if (inserted) + break; } if (!inserted) { GlyphSheet sheet = new GlyphSheet(); sheets.Add(sheet); - InsertGlyph(glyph, bmp, sheet); + InsertGlyph(glyph, bmp, rect, sheet); } } } @@ -103,14 +98,17 @@ namespace OpenTK.Graphics.Text #region Private Members - void InsertGlyph(Glyph glyph, Bitmap bmp, GlyphSheet sheet) + // Asks the packer for an empty space and writes the glyph there. + bool InsertGlyph(Glyph glyph, Bitmap bmp, Rectangle source, GlyphSheet sheet) { - Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height); - Rectangle target = sheet.Packer.Add(source); + Rectangle target = new Rectangle(); + if (!sheet.Packer.TryAdd(source, out target)) + return false; sheet.Texture.WriteRegion(source, target, 0, bmp); - cached_glyphs.Add(glyph, new CachedGlyphInfo(sheet.Texture, target)); + + return true; } #endregion diff --git a/Source/Utilities/Graphics/Text/GlyphPacker.cs b/Source/Utilities/Graphics/Text/GlyphPacker.cs index dd3ccb80..9cda0dd0 100644 --- a/Source/Utilities/Graphics/Text/GlyphPacker.cs +++ b/Source/Utilities/Graphics/Text/GlyphPacker.cs @@ -53,6 +53,64 @@ namespace OpenTK.Graphics.Text #region --- Public Methods --- + #region public bool TryAdd(Rectangle boundingBox) + + /// + /// Adds boundingBox to the GlyphPacker. + /// + /// The bounding box of the item to pack. + /// The System.Drawing.Rectangle that contains the position of the packed item. + /// True, if the item was successfully packed; false if the item is too big for this packer.. + /// Occurs if the item is larger than the available TexturePacker area + /// Occurs if the item cannot fit in the remaining packer space. + public bool TryAdd(Rectangle boundingBox, out Rectangle packedRectangle) + { + if (!root.Rectangle.Contains(boundingBox)) + { + packedRectangle = new Rectangle(); + return false; + } + + // Increase size so that the glyphs do not touch each other (to avoid rendering artifacts). + boundingBox.Width += 2; + boundingBox.Height += 2; + + Node node = root.Insert(boundingBox); + + // Tree is full and insertion failed: + if (node == null) + { + packedRectangle = new Rectangle(); + return false; + } + + packedRectangle = new Rectangle(node.Rectangle.X, node.Rectangle.Y, node.Rectangle.Width - 2, node.Rectangle.Height - 2); + return true; + } + + #endregion + + #region public Rectangle TryAdd(RectangleF boundingBox) + + /// + /// Adds boundingBox to the GlyphPacker. + /// + /// The bounding box of the item to pack. + /// The System.Drawing.RectangleF that contains the position of the packed item. + /// True, if the item was successfully packed; false if the item is too big for this packer.. + /// Occurs if the item is larger than the available TexturePacker area + /// Occurs if the item cannot fit in the remaining packer space. + public bool TryAdd(RectangleF boundingBox, out RectangleF packedRectangle) + { + Rectangle bbox = new Rectangle( + (int)boundingBox.X, (int)boundingBox.Y, + (int)(boundingBox.Width + 0.5f), (int)(boundingBox.Height + 0.5f)); + + return TryAdd(bbox, out packedRectangle); + } + + #endregion + #region public Rectangle Add(Rectangle boundingBox) /// @@ -61,24 +119,13 @@ namespace OpenTK.Graphics.Text /// The bounding box of the item to pack. /// A System.Drawing.Rectangle containing the coordinates of the packed item. /// Occurs if the item is larger than the available TexturePacker area - /// Occurs if the item already exists in the TexturePacker. + /// Occurs if the item cannot fit in the remaining packer space. public Rectangle Add(Rectangle boundingBox) { - if (!root.Rectangle.Contains(boundingBox)) - throw new InvalidOperationException("The item is too large for this TexturePacker"); - - Node node; - // Increase size so that the glyphs do not touch each other (to avoid rendering artifacts). - boundingBox.Width += 2; - boundingBox.Height += 2; - node = root.Insert(boundingBox); - - // Tree is full and insertion failed: - if (node == null) + if (!TryAdd(boundingBox, out boundingBox)) throw new TexturePackerFullException(); - return new Rectangle(node.Rectangle.X, node.Rectangle.Y, node.Rectangle.Width - 2, node.Rectangle.Height - 2); - //return node.Rectangle; + return boundingBox; } #endregion @@ -115,22 +162,6 @@ namespace OpenTK.Graphics.Text #endregion - #region public void ChangeSize(int new_width, int new_height) - - /// - /// Changes the dimensions of the TexturePacker surface. - /// - /// The new width of the TexturePacker surface. - /// The new height of the TexturePacker surface. - /// Changing the size of the TexturePacker surface will implicitly call TexturePacker.Clear(). - /// - public void ChangeSize(int new_width, int new_height) - { - throw new NotImplementedException(); - } - - #endregion - #endregion #region Node