Removed unused code.

Implemented Glyph enumerator for TextBlock.
GdiPlusGlyphRasterizer.Rasterize now reuses its Bitmap surface, if possible.
This commit is contained in:
the_fiddler 2008-11-25 22:16:40 +00:00
parent 26af1aa354
commit afa76c9894
8 changed files with 231 additions and 128 deletions

View file

@ -59,10 +59,6 @@ namespace OpenTK.Graphics.Text
{
TextExtents extents = rasterizer.MeasureText(block);
foreach (char c in block.Text)
if (c != '\n' && c != '\r' && !Char.IsWhiteSpace(c) && !cache.Contains(c, block.Font))
cache.Add(c, block.Font);
//GL.BindTexture(TextureTarget.Texture2D, 2);
//GL.Begin(BeginMode.Quads);
@ -82,20 +78,20 @@ namespace OpenTK.Graphics.Text
// Build layout
int current = 0;
foreach (char c in block.Text)
foreach (Glyph glyph in block)
{
if (c == '\n' || c == '\r')
continue;
else if (Char.IsWhiteSpace(c))
if (glyph.IsWhiteSpace)
{
current++;
continue;
}
else if (!cache.Contains(glyph))
cache.Add(glyph);
CachedGlyphInfo info = cache[c, block.Font];
CachedGlyphInfo info = cache[glyph];
RectangleF position = extents[current++];
// Use the real glyph width instead of the measured one
// (we want to achieve pixel perfect output).
// Use the real glyph width instead of the measured one (we want to achieve pixel perfect output).
position.Size = info.Rectangle.Size;
if (!active_lists.ContainsKey(info.Texture))

View file

@ -49,6 +49,9 @@ namespace OpenTK.Graphics.Text
TextExtents extents = new TextExtents();
Bitmap glyph_surface;
System.Drawing.Graphics glyph_renderer;
// Check the constructor, too, for additional flags.
static readonly StringFormat default_string_format = StringFormat.GenericTypographic;
static readonly StringFormat load_glyph_string_format = StringFormat.GenericDefault;
@ -75,15 +78,14 @@ namespace OpenTK.Graphics.Text
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))
{
SetTextRenderingOptions(gfx, glyph.Font);
EnsureSurfaceSize(ref glyph_surface, ref glyph_renderer, glyph.Font);
gfx.DrawString(glyph.Character.ToString(), glyph.Font, Brushes.White, PointF.Empty,
glyph.Font.Style == FontStyle.Italic ? load_glyph_string_format : default_string_format);
return bmp.Clone(FindEdges(bmp), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
}
SetTextRenderingOptions(glyph_renderer, glyph.Font);
glyph_renderer.Clear(Color.Transparent);
glyph_renderer.DrawString(glyph.Character.ToString(), glyph.Font, Brushes.White, PointF.Empty,
glyph.Font.Style == FontStyle.Italic ? load_glyph_string_format : default_string_format);
return glyph_surface.Clone(FindEdges(glyph_surface), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
}
#endregion
@ -111,6 +113,24 @@ namespace OpenTK.Graphics.Text
#region Private Members
#region EnsureSurfaceSize
void EnsureSurfaceSize(ref Bitmap bmp, ref System.Drawing.Graphics gfx, Font font)
{
if (bmp == null || bmp.Width < 2 * font.Size || bmp.Height < 2 * font.Size)
{
if (bmp != null)
bmp.Dispose();
if (gfx != null)
gfx.Dispose();
bmp = new Bitmap((int)(2 * font.Size), (int)(2 * font.Size));
gfx = System.Drawing.Graphics.FromImage(bmp);
}
}
#endregion
#region SetRenderingOptions
// Modify rendering settings (antialiasing, grid fitting) to improve appearance.

View file

@ -54,8 +54,8 @@ namespace OpenTK.Graphics.Text
#endregion
#region --- Public Methods ---
#region Public Methods
#region public char Character
/// <summary>
@ -88,6 +88,15 @@ namespace OpenTK.Graphics.Text
#endregion
#region public bool IsWhiteSpace
public bool IsWhiteSpace
{
get { return Char.IsWhiteSpace(Character); }
}
#endregion
#region public override bool Equals(object obj)
/// <summary>

View file

@ -27,15 +27,11 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using OpenTK.Graphics;
using System.Diagnostics;
namespace OpenTK.Graphics.Text
{
class GlyphCache
class GlyphCache// : IGlyphCache
{
#region Fields
@ -62,9 +58,8 @@ namespace OpenTK.Graphics.Text
#region Public Members
public void Add(char c, Font font)
public void Add(Glyph glyph)
{
Glyph glyph = new Glyph(c, font);
bool inserted = false;
using (Bitmap bmp = rasterizer.Rasterize(glyph))
@ -91,27 +86,9 @@ namespace OpenTK.Graphics.Text
}
}
void InsertGlyph(Glyph glyph, Bitmap bmp, GlyphSheet sheet)
public bool Contains(Glyph glyph)
{
Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height);
Rectangle target = sheet.Packer.Add(source);
sheet.Texture.WriteRegion(source, target, 0, bmp);
cached_glyphs.Add(glyph, new CachedGlyphInfo(sheet.Texture, target));
}
public bool Contains(char c, Font font)
{
return cached_glyphs.ContainsKey(new Glyph(c, font));
}
public CachedGlyphInfo this[char c, Font font]
{
get
{
return cached_glyphs[new Glyph(c, font)];
}
return cached_glyphs.ContainsKey(glyph);
}
public CachedGlyphInfo this[Glyph glyph]
@ -123,5 +100,19 @@ namespace OpenTK.Graphics.Text
}
#endregion
#region Private Members
void InsertGlyph(Glyph glyph, Bitmap bmp, GlyphSheet sheet)
{
Rectangle source = new Rectangle(0, 0, bmp.Width, bmp.Height);
Rectangle target = sheet.Packer.Add(source);
sheet.Texture.WriteRegion(source, target, 0, bmp);
cached_glyphs.Add(glyph, new CachedGlyphInfo(sheet.Texture, target));
}
#endregion
}
}

View file

@ -0,0 +1,107 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted.
//
// 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.Text;
using System.Drawing;
namespace OpenTK.Graphics.Text
{
class GlyphEnumerator : IEnumerator<Glyph>
{
#region Fields
string text;
Font font;
IEnumerator<char> implementation;
#endregion
#region Constructors
public GlyphEnumerator(string text, Font font)
{
if (text == null)
throw new ArgumentNullException("text");
if (font == null)
throw new ArgumentNullException("font");
this.text = text;
this.font = font;
implementation = text.GetEnumerator();
}
#endregion
#region IEnumerator<Glyph> Members
public Glyph Current
{
get { return new Glyph(implementation.Current, font); }
}
#endregion
#region IDisposable Members
public void Dispose()
{
implementation.Dispose();
}
#endregion
#region IEnumerator Members
object System.Collections.IEnumerator.Current
{
get { return new Glyph(implementation.Current, font); }
}
public bool MoveNext()
{
bool status;
do
{
status = implementation.MoveNext();
} while (status && (implementation.Current == '\n' || implementation.Current == '\r'));
return status;
}
public void Reset()
{
implementation.Reset();
}
#endregion
}
}

View file

@ -0,0 +1,36 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted.
//
// 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
namespace OpenTK.Graphics.Text
{
interface IGlyphCache
{
void Add(Glyph glyph);
void Contains(Glyph glyph);
CachedGlyphInfo this[Glyph glyph] { get; }
}
}

View file

@ -33,7 +33,7 @@ using System.Drawing;
namespace OpenTK.Graphics.Text
{
// Uniquely identifies a block of text. This structure can be used to identify text blocks for caching.
struct TextBlock : IEquatable<TextBlock>
struct TextBlock : IEquatable<TextBlock>, IEnumerable<Glyph>
{
#region Fields
@ -77,6 +77,11 @@ namespace OpenTK.Graphics.Text
return Text.GetHashCode() ^ Font.GetHashCode() ^ LayoutRectangle.GetHashCode() ^ Options.GetHashCode();
}
public Glyph this[int i]
{
get { return new Glyph(Text[i], Font); }
}
#endregion
#region IEquatable<TextBlock> Members
@ -91,5 +96,23 @@ namespace OpenTK.Graphics.Text
}
#endregion
#region IEnumerable<Glyph> Members
public IEnumerator<Glyph> GetEnumerator()
{
return new GlyphEnumerator(Text, Font);
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new GlyphEnumerator(Text, Font);
}
#endregion
}
}

View file

@ -140,20 +140,6 @@ namespace OpenTK.Graphics
throw new ArgumentNullException("font");
text_output.Print(new TextBlock(text, font, options, layoutRectangle), glyph_rasterizer, glyph_cache);
//glyph_rasterizer.MeasureText(text, font, options, layoutRectangle, ref text_extents);
//List<Vector2> vertices = new List<Vector2>();
//List<int> indices = new List<int>();
//PerformLayout(new TextBlock(text, font, layoutRectangle, options), text_extents, vertices, indices);
//GL.Begin(BeginMode.Triangles);
//foreach (int i in indices)
//{
// GL.TexCoord2(vertices[i + 1]);
// GL.Vertex2(vertices[i]);
//}
//GL.End();
}
#endregion
@ -200,70 +186,5 @@ namespace OpenTK.Graphics
#endregion
#endregion
#region Private Members
#region PerformLayout
void PerformLayout(TextBlock block, TextExtents extents, List<Vector2> vertices, List<int> indices)
{
vertices.Clear();
vertices.Capacity = 4 * block.Text.Length;
indices.Clear();
indices.Capacity = 6 * block.Text.Length;
float x_pos = 0, y_pos = 0;
RectangleF rect = new RectangleF();
float char_width, char_height;
// Every character comprises of 4 vertices, forming two triangles. We generate an index array which
// indexes vertices in a triangle-list fashion.
int current = 0;
foreach (char c in block.Text)
{
if (c == '\n' || c == '\r')
continue;
else if (Char.IsWhiteSpace(c))
{
current++;
continue;
}
else if (!glyph_cache.Contains(c, block.Font))
glyph_cache.Add(c, block.Font);
//font.GlyphData(c, out char_width, out char_height, out rect, out texture);
CachedGlyphInfo cache_info = glyph_cache[c, block.Font];
RectangleF glyph_position = extents[current];
x_pos = glyph_position.X;
y_pos = glyph_position.Y;
char_width = glyph_position.Width;
char_height = glyph_position.Height;
// Interleaved array: Vertex, TexCoord, Vertex, ...
vertices.Add(new Vector2(x_pos, y_pos)); // Vertex
vertices.Add(new Vector2(rect.Left, rect.Top)); // Texcoord
vertices.Add(new Vector2(x_pos, y_pos + char_height));
vertices.Add(new Vector2(rect.Left, rect.Bottom));
vertices.Add(new Vector2(x_pos + char_width, y_pos + char_height));
vertices.Add(new Vector2(rect.Right, rect.Bottom));
vertices.Add(new Vector2(x_pos + char_width, y_pos));
vertices.Add(new Vector2(rect.Right, rect.Top));
indices.Add(vertices.Count - 8);
indices.Add(vertices.Count - 6);
indices.Add(vertices.Count - 4);
indices.Add(vertices.Count - 4);
indices.Add(vertices.Count - 2);
indices.Add(vertices.Count - 8);
}
}
#endregion
#endregion
}
}