From e7e5e1453f5b4bd26db6d1106f439efddffb1772 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Thu, 12 Feb 2009 16:27:24 +0000 Subject: [PATCH] Added GL1.1 and GL1.2 rendering codepaths. Added selectable TextQuality level. Updated all interfaces to support the above. --- Source/Utilities/Graphics/ITextPrinter.cs | 8 +- .../Graphics/Text/GL11TextOutputProvider.cs | 55 +++++++++ .../Graphics/Text/GL12TextOutputProvider.cs | 48 ++++++++ .../Graphics/Text/GL1TextOutputProvider.cs | 47 +++++--- .../Graphics/Text/GdiPlusGlyphRasterizer .cs | 90 ++++++++------- Source/Utilities/Graphics/Text/GlyphCache.cs | 45 +++++--- Source/Utilities/Graphics/Text/GlyphSheet.cs | 18 +-- Source/Utilities/Graphics/Text/IGlyphCache.cs | 2 +- .../Graphics/Text/IGlyphRasterizer.cs | 5 +- .../Graphics/Text/ITextOutputProvider.cs | 2 +- Source/Utilities/Graphics/Text/TextExtents.cs | 2 + Source/Utilities/Graphics/Text/TextQuality.cs | 14 +++ Source/Utilities/Graphics/TextPrinter.cs | 108 +++++++++++++----- 13 files changed, 324 insertions(+), 120 deletions(-) create mode 100644 Source/Utilities/Graphics/Text/GL11TextOutputProvider.cs create mode 100644 Source/Utilities/Graphics/Text/GL12TextOutputProvider.cs create mode 100644 Source/Utilities/Graphics/Text/TextQuality.cs diff --git a/Source/Utilities/Graphics/ITextPrinter.cs b/Source/Utilities/Graphics/ITextPrinter.cs index f9c3dc22..882e2e50 100644 --- a/Source/Utilities/Graphics/ITextPrinter.cs +++ b/Source/Utilities/Graphics/ITextPrinter.cs @@ -20,11 +20,11 @@ namespace OpenTK.Graphics void Begin(); void End(); void Print(string text, Font font, Color color); - void Print(string text, Font font, Color color, RectangleF layoutRectangle); - void Print(string text, Font font, Color color, RectangleF layoutRectangle, TextPrinterOptions options); + void Print(string text, Font font, Color color, SizeF size); + void Print(string text, Font font, Color color, SizeF size, TextPrinterOptions options); TextExtents Measure(string text, Font font); - TextExtents Measure(string text, Font font, RectangleF layoutRectangle); - TextExtents Measure(string text, Font font, RectangleF layoutRectangle, TextPrinterOptions options); + TextExtents Measure(string text, Font font, SizeF size); + TextExtents Measure(string text, Font font, SizeF size, TextPrinterOptions options); [Obsolete("Use TextPrinter.Print instead")] void Draw(TextHandle handle); diff --git a/Source/Utilities/Graphics/Text/GL11TextOutputProvider.cs b/Source/Utilities/Graphics/Text/GL11TextOutputProvider.cs new file mode 100644 index 00000000..412ad4d4 --- /dev/null +++ b/Source/Utilities/Graphics/Text/GL11TextOutputProvider.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace OpenTK.Graphics.Text +{ + sealed class GL11TextOutputProvider : GL1TextOutputProvider + { + #region Fields + + TextQuality quality; + GlyphCache cache; + + #endregion + + #region Constuctors + + public GL11TextOutputProvider(TextQuality quality) + { + if (quality == TextQuality.High || quality == TextQuality.Default) + this.quality = TextQuality.Medium; + else + this.quality = quality; + + cache = new GlyphCache(); + } + + #endregion + + #region Protected Members + + protected override void SetBlendFunction() + { + GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); // For grayscale + } + + protected override void SetColor(Color color) + { + GL.Color4(color); + } + + protected override TextQuality TextQuality + { + get { return quality; } + } + + protected override GlyphCache Cache + { + get { return cache; } + } + + #endregion + } +} diff --git a/Source/Utilities/Graphics/Text/GL12TextOutputProvider.cs b/Source/Utilities/Graphics/Text/GL12TextOutputProvider.cs new file mode 100644 index 00000000..ba8575d2 --- /dev/null +++ b/Source/Utilities/Graphics/Text/GL12TextOutputProvider.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Drawing; + +namespace OpenTK.Graphics.Text +{ + sealed class GL12TextOutputProvider : GL1TextOutputProvider + { + #region Fields + + TextQuality quality; + GlyphCache cache; + + #endregion + + #region Constuctors + + public GL12TextOutputProvider(TextQuality quality) + { + this.quality = quality; + + cache = new GlyphCache(); + } + + #endregion + + protected override void SetBlendFunction() + { + GL.BlendFunc(BlendingFactorSrc.ConstantColorExt, BlendingFactorDest.OneMinusSrcColor); // For subpixel with color + } + + protected override void SetColor(Color color) + { + GL.BlendColor(color); + } + + protected override TextQuality TextQuality + { + get { return quality; } + } + + protected override GlyphCache Cache + { + get { return cache; } + } + } +} diff --git a/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs b/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs index 6ece3591..f37877c7 100644 --- a/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs +++ b/Source/Utilities/Graphics/Text/GL1TextOutputProvider.cs @@ -32,7 +32,7 @@ using System; namespace OpenTK.Graphics.Text { - class GL1TextOutputProvider : ITextOutputProvider + abstract class GL1TextOutputProvider : ITextOutputProvider { #region Fields @@ -57,22 +57,17 @@ namespace OpenTK.Graphics.Text #region Print - public void Print(TextBlock block, PointF location, Color color, IGlyphRasterizer rasterizer, GlyphCache cache) + public void Print(TextBlock block, Color color, IGlyphRasterizer rasterizer) { GL.PushAttrib(AttribMask.TextureBit | AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.DepthBufferBit); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); - GL.BlendFunc(BlendingFactorSrc.ConstantColorExt, BlendingFactorDest.OneMinusSrcColor); // For subpixel with color + SetBlendFunction(); GL.Disable(EnableCap.DepthTest); - //GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate); - //GL.Enable(EnableCap.ColorMaterial); - //GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); // For grayscale - //GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcColor); // For subpixel - - using (TextExtents extents = rasterizer.MeasureText(block, location)) + using (TextExtents extents = rasterizer.MeasureText(block)) { // Build layout int current = 0; @@ -83,10 +78,10 @@ namespace OpenTK.Graphics.Text current++; continue; } - else if (!cache.Contains(glyph)) - cache.Add(glyph); + else if (!Cache.Contains(glyph)) + Cache.Add(glyph, rasterizer, TextQuality); - CachedGlyphInfo info = cache[glyph]; + 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). @@ -123,12 +118,12 @@ namespace OpenTK.Graphics.Text key.Bind(); - GL.Translate(location.X, location.Y, 0); if (!legacy_mode) { GL.Scale(2.0 / (viewport[2] - viewport[0]), -2.0 / (viewport[3] - viewport[1]), 1); } - GL.BlendColor(color); + + SetColor(color); GL.Begin(BeginMode.Triangles); @@ -201,5 +196,29 @@ namespace OpenTK.Graphics.Text #endregion #endregion + + #region Protected Members + + protected abstract void SetBlendFunction(); + + protected abstract void SetColor(Color color); + + protected abstract TextQuality TextQuality { get; } + + protected abstract GlyphCache Cache { get; } + + #endregion + + #region Static Members + + public static GL1TextOutputProvider Create(TextQuality quality) + { + if (!GL.SupportsFunction("BlendFunc") || quality == TextQuality.Low || quality == TextQuality.Medium) + return new GL11TextOutputProvider(quality); + else + return new GL12TextOutputProvider(quality); + } + + #endregion } } diff --git a/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs b/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs index 6f5878d5..19d31bc8 100644 --- a/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs +++ b/Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs @@ -48,6 +48,8 @@ namespace OpenTK.Graphics.Text Bitmap glyph_surface; System.Drawing.Graphics glyph_renderer; + readonly List measured_glyphs = new List(256); + readonly ObjectPool text_extents_pool = new ObjectPool(); // Check the constructor, too, for additional flags. @@ -73,8 +75,7 @@ namespace OpenTK.Graphics.Text } } - public GdiPlusGlyphRasterizer() - { } + public GdiPlusGlyphRasterizer() { } #endregion @@ -84,15 +85,13 @@ namespace OpenTK.Graphics.Text public Bitmap Rasterize(Glyph glyph) { - //RectangleF r = MeasureText( - // new TextBlock( - // glyph.Character.ToString(), glyph.Font, - // TextPrinterOptions.NoCache, SizeF.Empty), - // PointF.Empty).BoundingBox; + return Rasterize(glyph, TextQuality.Default); + } + public Bitmap Rasterize(Glyph glyph, TextQuality quality) + { EnsureSurfaceSize(ref glyph_surface, ref glyph_renderer, glyph.Font); - - SetTextRenderingOptions(glyph_renderer, glyph.Font); + SetTextRenderingOptions(glyph_renderer, glyph.Font, quality); glyph_renderer.Clear(Color.Transparent); glyph_renderer.DrawString(glyph.Character.ToString(), glyph.Font, Brushes.White, PointF.Empty, @@ -103,32 +102,16 @@ namespace OpenTK.Graphics.Text return glyph_surface.Clone(r2, System.Drawing.Imaging.PixelFormat.Format32bppArgb); } - public void Rasterize(Glyph glyph, ref Bitmap bmp, out Rectangle rect) - { - EnsureSurfaceSize(ref bmp, ref glyph_renderer, glyph.Font); - - using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(bmp)) - { - SetTextRenderingOptions(gfx, glyph.Font); - - //gfx.Clear(Color.Transparent); - //gfx.Clear(Color.FromArgb(255, 0, 0, 0)); - //gfx.DrawString(glyph.Character.ToString(), glyph.Font, Brushes.White, PointF.Empty, - // glyph.Font.Style & FontStyle.Italic != 0 ? load_glyph_string_format : default_string_format); - System.Windows.Forms.TextRenderer.DrawText(gfx, glyph.Character.ToString(), glyph.Font, Point.Empty, Color.White); - //, - // (glyph.Font.Style & FontStyle.Italic) != 0 ? - // System.Windows.Forms.TextFormatFlags.GlyphOverhangPadding : - // System.Windows.Forms.TextFormatFlags.Default); - rect = FindEdges(bmp); - } - } - #endregion #region MeasureText - public TextExtents MeasureText(TextBlock block, PointF location) + public TextExtents MeasureText(TextBlock block) + { + return MeasureText(block, TextQuality.Default); + } + + public TextExtents MeasureText(TextBlock block, TextQuality quality) { // First, check if we have cached this text block. Do not use block_cache.TryGetValue, to avoid thrashing // the user's TextBlockExtents struct. @@ -136,7 +119,7 @@ namespace OpenTK.Graphics.Text return block_cache[block]; // If this block is not cached, we have to measure it and (potentially) place it in the cache. - TextExtents extents = MeasureTextExtents(block); + TextExtents extents = MeasureTextExtents(block, quality); if ((block.Options & TextPrinterOptions.NoCache) == 0) block_cache.Add(block, extents); @@ -171,21 +154,39 @@ namespace OpenTK.Graphics.Text #region SetRenderingOptions // Modify rendering settings (antialiasing, grid fitting) to improve appearance. - void SetTextRenderingOptions(System.Drawing.Graphics gfx, Font font) + void SetTextRenderingOptions(System.Drawing.Graphics gfx, Font font, TextQuality quality) { - // Small sizes look blurry without gridfitting, so turn that on. - //if (font.Size <= 18.0f) - // gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; - //else - gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; - //gfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; + switch (quality) + { + case TextQuality.Default: + gfx.TextRenderingHint = TextRenderingHint.SystemDefault; + break; + + case TextQuality.High: + gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; + break; + + case TextQuality.Medium: + if (font.Size <= 18.0f) + gfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; + else + gfx.TextRenderingHint = TextRenderingHint.AntiAlias; + break; + + case TextQuality.Low: + if (font.Size <= 18.0f) + gfx.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; + else + gfx.TextRenderingHint = TextRenderingHint.SingleBitPerPixel; + break; + } } #endregion #region MeasureTextExtents - TextExtents MeasureTextExtents(TextBlock block) + TextExtents MeasureTextExtents(TextBlock block, TextQuality quality) { // Todo: Parse layout options: //StringFormat format = default_string_format; @@ -199,7 +200,7 @@ namespace OpenTK.Graphics.Text if (block.Bounds == SizeF.Empty) rect.Size = MaximumGraphicsClipSize; - SetTextRenderingOptions(graphics, block.Font); + SetTextRenderingOptions(graphics, block.Font, quality); IntPtr native_graphics = GdiPlus.GetNativeGraphics(graphics); IntPtr native_font = GdiPlus.GetNativeFont(block.Font); @@ -239,6 +240,8 @@ namespace OpenTK.Graphics.Text IEnumerable MeasureGlyphExtents(string text, int height, RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format) { + measured_glyphs.Clear(); + RectangleF rect = new RectangleF(); int current = 0; while (current < text.Length) @@ -277,11 +280,14 @@ namespace OpenTK.Graphics.Text rect.Y += height; - yield return rect; + //yield return rect; + measured_glyphs.Add(rect); } current += num_characters; } + + return measured_glyphs; } #endregion diff --git a/Source/Utilities/Graphics/Text/GlyphCache.cs b/Source/Utilities/Graphics/Text/GlyphCache.cs index fa99e041..090f9a9f 100644 --- a/Source/Utilities/Graphics/Text/GlyphCache.cs +++ b/Source/Utilities/Graphics/Text/GlyphCache.cs @@ -31,41 +31,54 @@ using System.Drawing; namespace OpenTK.Graphics.Text { - class GlyphCache : IGlyphCache + abstract class GlyphCache : IGlyphCache + { + #region IGlyphCache Members + + public abstract void Add(Glyph glyph, IGlyphRasterizer rasterizer, TextQuality quality); + + public abstract bool Contains(Glyph glyph); + + public abstract CachedGlyphInfo this[Glyph glyph] { get; } + + #endregion + } + + class GlyphCache : GlyphCache where T : Texture2D { #region Fields - IGlyphRasterizer rasterizer; - List sheets = new List(); + List> sheets = new List>(); Bitmap bmp = new Bitmap(32, 32); Dictionary cached_glyphs = new Dictionary(); + const int SheetWidth = 512, SheetHeight = 512; + #endregion #region Constructors - public GlyphCache(IGlyphRasterizer rasterizer) + public GlyphCache() { - if (rasterizer == null) - throw new ArgumentNullException("rasterizer"); - - this.rasterizer = rasterizer; - sheets.Add(new GlyphSheet()); + sheets.Add(new GlyphSheet(SheetWidth, SheetHeight)); } #endregion #region IGlyphCache Members - public void Add(Glyph glyph) + public override void Add(Glyph glyph, IGlyphRasterizer rasterizer, TextQuality quality) { + if (rasterizer == null) + throw new ArgumentNullException("rasterizer"); + bool inserted = false; - using (Bitmap bmp = rasterizer.Rasterize(glyph)) + using (Bitmap bmp = rasterizer.Rasterize(glyph, quality)) { Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); - foreach (GlyphSheet sheet in sheets) + foreach (GlyphSheet sheet in sheets) { inserted = InsertGlyph(glyph, bmp, rect, sheet); if (inserted) @@ -74,19 +87,19 @@ namespace OpenTK.Graphics.Text if (!inserted) { - GlyphSheet sheet = new GlyphSheet(); + GlyphSheet sheet = new GlyphSheet(SheetWidth, SheetHeight); sheets.Add(sheet); InsertGlyph(glyph, bmp, rect, sheet); } } } - public bool Contains(Glyph glyph) + public override bool Contains(Glyph glyph) { return cached_glyphs.ContainsKey(glyph); } - public CachedGlyphInfo this[Glyph glyph] + public override CachedGlyphInfo this[Glyph glyph] { get { @@ -99,7 +112,7 @@ namespace OpenTK.Graphics.Text #region Private Members // Asks the packer for an empty space and writes the glyph there. - bool InsertGlyph(Glyph glyph, Bitmap bmp, Rectangle source, GlyphSheet sheet) + bool InsertGlyph(Glyph glyph, Bitmap bmp, Rectangle source, GlyphSheet sheet) { Rectangle target = new Rectangle(); if (!sheet.Packer.TryAdd(source, out target)) diff --git a/Source/Utilities/Graphics/Text/GlyphSheet.cs b/Source/Utilities/Graphics/Text/GlyphSheet.cs index 3b929437..655638c4 100644 --- a/Source/Utilities/Graphics/Text/GlyphSheet.cs +++ b/Source/Utilities/Graphics/Text/GlyphSheet.cs @@ -32,35 +32,35 @@ using System.Drawing; namespace OpenTK.Graphics.Text { - class GlyphSheet + class GlyphSheet where T : Texture2D { #region Fields - //AlphaTexture2D texture; - RgbaTexture2D texture = new RgbaTexture2D(512, 512); - GlyphPacker packer = new GlyphPacker(512, 512); + readonly T texture; + readonly GlyphPacker packer; #endregion #region Constructors - public GlyphSheet() - { } + public GlyphSheet(int width, int height) + { + texture = (T)typeof(T).GetConstructor(new Type[] { typeof(int), typeof(int) }).Invoke(new object[] { width, height }); + packer = new GlyphPacker(width, height); + } #endregion #region Public Members - public Texture2D Texture + public T Texture { get { return texture; } - private set { texture = (RgbaTexture2D)value; } } public GlyphPacker Packer { get { return packer; } - private set { packer = value; } } #endregion diff --git a/Source/Utilities/Graphics/Text/IGlyphCache.cs b/Source/Utilities/Graphics/Text/IGlyphCache.cs index 49195888..d18a7dd7 100644 --- a/Source/Utilities/Graphics/Text/IGlyphCache.cs +++ b/Source/Utilities/Graphics/Text/IGlyphCache.cs @@ -29,7 +29,7 @@ namespace OpenTK.Graphics.Text { interface IGlyphCache { - void Add(Glyph glyph); + void Add(Glyph glyph, IGlyphRasterizer rasterizer, TextQuality quality); bool Contains(Glyph glyph); CachedGlyphInfo this[Glyph glyph] { get; } } diff --git a/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs b/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs index e52260c2..e5d60594 100644 --- a/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs +++ b/Source/Utilities/Graphics/Text/IGlyphRasterizer.cs @@ -37,7 +37,8 @@ namespace OpenTK.Graphics.Text interface IGlyphRasterizer { Bitmap Rasterize(Glyph glyph); - TextExtents MeasureText(TextBlock block, PointF location); - void Rasterize(Glyph glyph, ref Bitmap bmp, out Rectangle rect); + Bitmap Rasterize(Glyph glyph, TextQuality quality); + TextExtents MeasureText(TextBlock block); + TextExtents MeasureText(TextBlock block, TextQuality quality); } } diff --git a/Source/Utilities/Graphics/Text/ITextOutputProvider.cs b/Source/Utilities/Graphics/Text/ITextOutputProvider.cs index 34a219d2..fe0902ef 100644 --- a/Source/Utilities/Graphics/Text/ITextOutputProvider.cs +++ b/Source/Utilities/Graphics/Text/ITextOutputProvider.cs @@ -34,7 +34,7 @@ namespace OpenTK.Graphics.Text { interface ITextOutputProvider { - void Print(TextBlock block, PointF location, Color color, IGlyphRasterizer rasterizer, GlyphCache cache); + void Print(TextBlock block, Color color, IGlyphRasterizer rasterizer); void Begin(); void End(); } diff --git a/Source/Utilities/Graphics/Text/TextExtents.cs b/Source/Utilities/Graphics/Text/TextExtents.cs index c8a241a7..03a923a2 100644 --- a/Source/Utilities/Graphics/Text/TextExtents.cs +++ b/Source/Utilities/Graphics/Text/TextExtents.cs @@ -40,6 +40,8 @@ namespace OpenTK.Graphics.Text protected RectangleF text_extents; protected List glyph_extents = new List(); + public static readonly TextExtents Empty = new TextExtents(); + #endregion #region Constructors diff --git a/Source/Utilities/Graphics/Text/TextQuality.cs b/Source/Utilities/Graphics/Text/TextQuality.cs new file mode 100644 index 00000000..7ed091f5 --- /dev/null +++ b/Source/Utilities/Graphics/Text/TextQuality.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Graphics.Text +{ + public enum TextQuality + { + Default = 0, + Low, + Medium, + High + } +} diff --git a/Source/Utilities/Graphics/TextPrinter.cs b/Source/Utilities/Graphics/TextPrinter.cs index 133289ca..c285ec0e 100644 --- a/Source/Utilities/Graphics/TextPrinter.cs +++ b/Source/Utilities/Graphics/TextPrinter.cs @@ -30,9 +30,9 @@ namespace OpenTK.Graphics { #region Fields - GlyphCache glyph_cache; IGlyphRasterizer glyph_rasterizer; ITextOutputProvider text_output; + TextQuality text_quality; #endregion @@ -42,21 +42,16 @@ namespace OpenTK.Graphics /// Constructs a new TextPrinter object. /// public TextPrinter() - : this(null, null) + : this(null, null, TextQuality.Default) { } + + public TextPrinter(TextQuality quality) + : this(null, null, quality) { } + + TextPrinter(IGlyphRasterizer rasterizer, ITextOutputProvider output, TextQuality quality) { - } - - TextPrinter(IGlyphRasterizer rasterizer, ITextOutputProvider output/*, IGlyphCacheProvider, ITextOutputProvider */) - { - if (rasterizer == null) - rasterizer = new GdiPlusGlyphRasterizer(); - - if (output == null) - output = new GL1TextOutputProvider(); - glyph_rasterizer = rasterizer; - glyph_cache = new GlyphCache(rasterizer); text_output = output; + text_quality = quality; } #endregion @@ -71,7 +66,7 @@ namespace OpenTK.Graphics [Obsolete] public void Begin() { - text_output.Begin(); + TextOutput.Begin(); } #endregion @@ -84,7 +79,7 @@ namespace OpenTK.Graphics [Obsolete] public void End() { - text_output.End(); + TextOutput.End(); } #endregion @@ -93,25 +88,20 @@ namespace OpenTK.Graphics public void Print(string text, Font font, Color color) { - Print(text, font, color, RectangleF.Empty, TextPrinterOptions.Default); + Print(text, font, color, SizeF.Empty, TextPrinterOptions.Default); } - public void Print(string text, Font font, Color color, RectangleF layoutRectangle) + public void Print(string text, Font font, Color color, SizeF size) { - Print(text, font, color, layoutRectangle, TextPrinterOptions.Default); + Print(text, font, color, size, TextPrinterOptions.Default); } - public void Print(string text, Font font, Color color, RectangleF layoutRectangle, TextPrinterOptions options) + public void Print(string text, Font font, Color color, SizeF size, TextPrinterOptions options) { - if (String.IsNullOrEmpty(text)) + if (!ValidateParameters(text, font, size)) return; - if (font == null) - throw new ArgumentNullException("font"); - - //text_output.Begin(); - text_output.Print(new TextBlock(text, font, options, layoutRectangle.Size), layoutRectangle.Location, color, glyph_rasterizer, glyph_cache); - //text_output.End(); + text_output.Print(new TextBlock(text, font, options, size), color, Rasterizer); } #endregion @@ -120,17 +110,30 @@ namespace OpenTK.Graphics public TextExtents Measure(string text, Font font) { - return Measure(text, font, RectangleF.Empty, TextPrinterOptions.Default); + return Measure(text, font, SizeF.Empty, TextPrinterOptions.Default); } - public TextExtents Measure(string text, Font font, RectangleF layoutRectangle) + public TextExtents Measure(string text, Font font, SizeF size) { - return Measure(text, font, layoutRectangle, TextPrinterOptions.Default); + return Measure(text, font, size, TextPrinterOptions.Default); } - public TextExtents Measure(string text, Font font, RectangleF layoutRectangle, TextPrinterOptions options) + public TextExtents Measure(string text, Font font, SizeF size, TextPrinterOptions options) { - return glyph_rasterizer.MeasureText(new TextBlock(text, font, options, layoutRectangle.Size), layoutRectangle.Location); + if (!ValidateParameters(text, font, size)) + return TextExtents.Empty; + + return Rasterizer.MeasureText(new TextBlock(text, font, options, size)); + } + + #endregion + + #region Clear() + + public void Clear() + { + //glyph_cache.Clear(); + throw new NotImplementedException(); } #endregion @@ -158,5 +161,48 @@ namespace OpenTK.Graphics #endregion #endregion + + #region Private Members + + IGlyphRasterizer Rasterizer + { + get + { + if (glyph_rasterizer == null) + glyph_rasterizer = new GdiPlusGlyphRasterizer(); + + return glyph_rasterizer; + } + + } + + ITextOutputProvider TextOutput + { + get + { + if (text_output == null) + text_output = GL1TextOutputProvider.Create(text_quality); + + return text_output; + } + } + + #endregion + + #region Static Members + + static bool ValidateParameters(string text, Font font, SizeF size) + { + if (String.IsNullOrEmpty(text)) + return false; + if (font == null) + throw new ArgumentNullException("font"); + if (size.Width < 0 || size.Height < 0) + throw new ArgumentOutOfRangeException("size"); + + return true; + } + + #endregion } }