Remove exceptions from the typical path (significant speed increase).

This commit is contained in:
the_fiddler 2008-11-26 15:35:15 +00:00
parent a26b75f3af
commit a868c4b4e8
2 changed files with 74 additions and 45 deletions

View file

@ -37,7 +37,7 @@ namespace OpenTK.Graphics.Text
IGlyphRasterizer rasterizer; IGlyphRasterizer rasterizer;
List<GlyphSheet> sheets = new List<GlyphSheet>(); List<GlyphSheet> sheets = new List<GlyphSheet>();
Bitmap bmp = new Bitmap(256, 256); Bitmap bmp = new Bitmap(32, 32);
Dictionary<Glyph, CachedGlyphInfo> cached_glyphs = new Dictionary<Glyph, CachedGlyphInfo>(); Dictionary<Glyph, CachedGlyphInfo> cached_glyphs = new Dictionary<Glyph, CachedGlyphInfo>();
@ -64,24 +64,19 @@ namespace OpenTK.Graphics.Text
using (Bitmap bmp = rasterizer.Rasterize(glyph)) using (Bitmap bmp = rasterizer.Rasterize(glyph))
{ {
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
foreach (GlyphSheet sheet in sheets) foreach (GlyphSheet sheet in sheets)
{ {
try inserted = InsertGlyph(glyph, bmp, rect, sheet);
{ if (inserted)
InsertGlyph(glyph, bmp, sheet); break;
inserted = true;
break;
}
catch (TexturePackerFullException)
{
}
} }
if (!inserted) if (!inserted)
{ {
GlyphSheet sheet = new GlyphSheet(); GlyphSheet sheet = new GlyphSheet();
sheets.Add(sheet); sheets.Add(sheet);
InsertGlyph(glyph, bmp, sheet); InsertGlyph(glyph, bmp, rect, sheet);
} }
} }
} }
@ -103,14 +98,17 @@ namespace OpenTK.Graphics.Text
#region Private Members #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 = new Rectangle();
Rectangle target = sheet.Packer.Add(source); if (!sheet.Packer.TryAdd(source, out target))
return false;
sheet.Texture.WriteRegion(source, target, 0, bmp); sheet.Texture.WriteRegion(source, target, 0, bmp);
cached_glyphs.Add(glyph, new CachedGlyphInfo(sheet.Texture, target)); cached_glyphs.Add(glyph, new CachedGlyphInfo(sheet.Texture, target));
return true;
} }
#endregion #endregion

View file

@ -53,6 +53,64 @@ namespace OpenTK.Graphics.Text
#region --- Public Methods --- #region --- Public Methods ---
#region public bool TryAdd(Rectangle boundingBox)
/// <summary>
/// Adds boundingBox to the GlyphPacker.
/// </summary>
/// <param name="boundingBox">The bounding box of the item to pack.</param>
/// <param name="packedRectangle">The System.Drawing.Rectangle that contains the position of the packed item.</param>
/// <returns>True, if the item was successfully packed; false if the item is too big for this packer..</returns>
/// <exception cref="InvalidOperationException">Occurs if the item is larger than the available TexturePacker area</exception>
/// <exception cref="TexturePackerFullException">Occurs if the item cannot fit in the remaining packer space.</exception>
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)
/// <summary>
/// Adds boundingBox to the GlyphPacker.
/// </summary>
/// <param name="boundingBox">The bounding box of the item to pack.</param>
/// <param name="packedRectangle">The System.Drawing.RectangleF that contains the position of the packed item.</param>
/// <returns>True, if the item was successfully packed; false if the item is too big for this packer..</returns>
/// <exception cref="InvalidOperationException">Occurs if the item is larger than the available TexturePacker area</exception>
/// <exception cref="TexturePackerFullException">Occurs if the item cannot fit in the remaining packer space.</exception>
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) #region public Rectangle Add(Rectangle boundingBox)
/// <summary> /// <summary>
@ -61,24 +119,13 @@ namespace OpenTK.Graphics.Text
/// <param name="boundingBox">The bounding box of the item to pack.</param> /// <param name="boundingBox">The bounding box of the item to pack.</param>
/// <returns>A System.Drawing.Rectangle containing the coordinates of the packed item.</returns> /// <returns>A System.Drawing.Rectangle containing the coordinates of the packed item.</returns>
/// <exception cref="InvalidOperationException">Occurs if the item is larger than the available TexturePacker area</exception> /// <exception cref="InvalidOperationException">Occurs if the item is larger than the available TexturePacker area</exception>
/// <exception cref="ArgumentException">Occurs if the item already exists in the TexturePacker.</exception> /// <exception cref="TexturePackerFullException">Occurs if the item cannot fit in the remaining packer space.</exception>
public Rectangle Add(Rectangle boundingBox) public Rectangle Add(Rectangle boundingBox)
{ {
if (!root.Rectangle.Contains(boundingBox)) if (!TryAdd(boundingBox, out 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)
throw new TexturePackerFullException(); throw new TexturePackerFullException();
return new Rectangle(node.Rectangle.X, node.Rectangle.Y, node.Rectangle.Width - 2, node.Rectangle.Height - 2); return boundingBox;
//return node.Rectangle;
} }
#endregion #endregion
@ -115,22 +162,6 @@ namespace OpenTK.Graphics.Text
#endregion #endregion
#region public void ChangeSize(int new_width, int new_height)
/// <summary>
/// Changes the dimensions of the TexturePacker surface.
/// </summary>
/// <param name="new_width">The new width of the TexturePacker surface.</param>
/// <param name="new_height">The new height of the TexturePacker surface.</param>
/// <remarks>Changing the size of the TexturePacker surface will implicitly call TexturePacker.Clear().</remarks>
/// <seealso cref="Clear"/>
public void ChangeSize(int new_width, int new_height)
{
throw new NotImplementedException();
}
#endregion
#endregion #endregion
#region Node #region Node