mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-07-10 14:57:25 +00:00
Added GL1.1 and GL1.2 rendering codepaths.
Added selectable TextQuality level. Updated all interfaces to support the above.
This commit is contained in:
parent
1502fc27b7
commit
e7e5e1453f
|
@ -20,11 +20,11 @@ namespace OpenTK.Graphics
|
||||||
void Begin();
|
void Begin();
|
||||||
void End();
|
void End();
|
||||||
void Print(string text, Font font, Color color);
|
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, SizeF size);
|
||||||
void Print(string text, Font font, Color color, RectangleF layoutRectangle, TextPrinterOptions options);
|
void Print(string text, Font font, Color color, SizeF size, TextPrinterOptions options);
|
||||||
TextExtents Measure(string text, Font font);
|
TextExtents Measure(string text, Font font);
|
||||||
TextExtents Measure(string text, Font font, RectangleF layoutRectangle);
|
TextExtents Measure(string text, Font font, SizeF size);
|
||||||
TextExtents Measure(string text, Font font, RectangleF layoutRectangle, TextPrinterOptions options);
|
TextExtents Measure(string text, Font font, SizeF size, TextPrinterOptions options);
|
||||||
|
|
||||||
[Obsolete("Use TextPrinter.Print instead")]
|
[Obsolete("Use TextPrinter.Print instead")]
|
||||||
void Draw(TextHandle handle);
|
void Draw(TextHandle handle);
|
||||||
|
|
55
Source/Utilities/Graphics/Text/GL11TextOutputProvider.cs
Normal file
55
Source/Utilities/Graphics/Text/GL11TextOutputProvider.cs
Normal file
|
@ -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<AlphaTexture2D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
}
|
48
Source/Utilities/Graphics/Text/GL12TextOutputProvider.cs
Normal file
48
Source/Utilities/Graphics/Text/GL12TextOutputProvider.cs
Normal file
|
@ -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<RgbaTexture2D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ using System;
|
||||||
|
|
||||||
namespace OpenTK.Graphics.Text
|
namespace OpenTK.Graphics.Text
|
||||||
{
|
{
|
||||||
class GL1TextOutputProvider : ITextOutputProvider
|
abstract class GL1TextOutputProvider : ITextOutputProvider
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
|
@ -57,22 +57,17 @@ namespace OpenTK.Graphics.Text
|
||||||
|
|
||||||
#region Print
|
#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.PushAttrib(AttribMask.TextureBit | AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.DepthBufferBit);
|
||||||
|
|
||||||
GL.Enable(EnableCap.Texture2D);
|
GL.Enable(EnableCap.Texture2D);
|
||||||
GL.Enable(EnableCap.Blend);
|
GL.Enable(EnableCap.Blend);
|
||||||
GL.BlendFunc(BlendingFactorSrc.ConstantColorExt, BlendingFactorDest.OneMinusSrcColor); // For subpixel with color
|
SetBlendFunction();
|
||||||
|
|
||||||
GL.Disable(EnableCap.DepthTest);
|
GL.Disable(EnableCap.DepthTest);
|
||||||
|
|
||||||
//GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate);
|
using (TextExtents extents = rasterizer.MeasureText(block))
|
||||||
//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))
|
|
||||||
{
|
{
|
||||||
// Build layout
|
// Build layout
|
||||||
int current = 0;
|
int current = 0;
|
||||||
|
@ -83,10 +78,10 @@ namespace OpenTK.Graphics.Text
|
||||||
current++;
|
current++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!cache.Contains(glyph))
|
else if (!Cache.Contains(glyph))
|
||||||
cache.Add(glyph);
|
Cache.Add(glyph, rasterizer, TextQuality);
|
||||||
|
|
||||||
CachedGlyphInfo info = cache[glyph];
|
CachedGlyphInfo info = Cache[glyph];
|
||||||
RectangleF position = extents[current++];
|
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).
|
||||||
|
@ -123,12 +118,12 @@ namespace OpenTK.Graphics.Text
|
||||||
|
|
||||||
key.Bind();
|
key.Bind();
|
||||||
|
|
||||||
GL.Translate(location.X, location.Y, 0);
|
|
||||||
if (!legacy_mode)
|
if (!legacy_mode)
|
||||||
{
|
{
|
||||||
GL.Scale(2.0 / (viewport[2] - viewport[0]), -2.0 / (viewport[3] - viewport[1]), 1);
|
GL.Scale(2.0 / (viewport[2] - viewport[0]), -2.0 / (viewport[3] - viewport[1]), 1);
|
||||||
}
|
}
|
||||||
GL.BlendColor(color);
|
|
||||||
|
SetColor(color);
|
||||||
|
|
||||||
GL.Begin(BeginMode.Triangles);
|
GL.Begin(BeginMode.Triangles);
|
||||||
|
|
||||||
|
@ -201,5 +196,29 @@ namespace OpenTK.Graphics.Text
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ namespace OpenTK.Graphics.Text
|
||||||
Bitmap glyph_surface;
|
Bitmap glyph_surface;
|
||||||
System.Drawing.Graphics glyph_renderer;
|
System.Drawing.Graphics glyph_renderer;
|
||||||
|
|
||||||
|
readonly List<RectangleF> measured_glyphs = new List<RectangleF>(256);
|
||||||
|
|
||||||
readonly ObjectPool<PoolableTextExtents> text_extents_pool = new ObjectPool<PoolableTextExtents>();
|
readonly ObjectPool<PoolableTextExtents> text_extents_pool = new ObjectPool<PoolableTextExtents>();
|
||||||
|
|
||||||
// Check the constructor, too, for additional flags.
|
// Check the constructor, too, for additional flags.
|
||||||
|
@ -73,8 +75,7 @@ namespace OpenTK.Graphics.Text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GdiPlusGlyphRasterizer()
|
public GdiPlusGlyphRasterizer() { }
|
||||||
{ }
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -84,15 +85,13 @@ namespace OpenTK.Graphics.Text
|
||||||
|
|
||||||
public Bitmap Rasterize(Glyph glyph)
|
public Bitmap Rasterize(Glyph glyph)
|
||||||
{
|
{
|
||||||
//RectangleF r = MeasureText(
|
return Rasterize(glyph, TextQuality.Default);
|
||||||
// new TextBlock(
|
}
|
||||||
// glyph.Character.ToString(), glyph.Font,
|
|
||||||
// TextPrinterOptions.NoCache, SizeF.Empty),
|
|
||||||
// PointF.Empty).BoundingBox;
|
|
||||||
|
|
||||||
|
public Bitmap Rasterize(Glyph glyph, TextQuality quality)
|
||||||
|
{
|
||||||
EnsureSurfaceSize(ref glyph_surface, ref glyph_renderer, glyph.Font);
|
EnsureSurfaceSize(ref glyph_surface, ref glyph_renderer, glyph.Font);
|
||||||
|
SetTextRenderingOptions(glyph_renderer, glyph.Font, quality);
|
||||||
SetTextRenderingOptions(glyph_renderer, glyph.Font);
|
|
||||||
|
|
||||||
glyph_renderer.Clear(Color.Transparent);
|
glyph_renderer.Clear(Color.Transparent);
|
||||||
glyph_renderer.DrawString(glyph.Character.ToString(), glyph.Font, Brushes.White, PointF.Empty,
|
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);
|
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
|
#endregion
|
||||||
|
|
||||||
#region MeasureText
|
#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
|
// First, check if we have cached this text block. Do not use block_cache.TryGetValue, to avoid thrashing
|
||||||
// the user's TextBlockExtents struct.
|
// the user's TextBlockExtents struct.
|
||||||
|
@ -136,7 +119,7 @@ namespace OpenTK.Graphics.Text
|
||||||
return block_cache[block];
|
return block_cache[block];
|
||||||
|
|
||||||
// If this block is not cached, we have to measure it and (potentially) place it in the cache.
|
// 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)
|
if ((block.Options & TextPrinterOptions.NoCache) == 0)
|
||||||
block_cache.Add(block, extents);
|
block_cache.Add(block, extents);
|
||||||
|
@ -171,21 +154,39 @@ namespace OpenTK.Graphics.Text
|
||||||
#region SetRenderingOptions
|
#region SetRenderingOptions
|
||||||
|
|
||||||
// Modify rendering settings (antialiasing, grid fitting) to improve appearance.
|
// 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.
|
switch (quality)
|
||||||
//if (font.Size <= 18.0f)
|
{
|
||||||
// gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
case TextQuality.Default:
|
||||||
//else
|
gfx.TextRenderingHint = TextRenderingHint.SystemDefault;
|
||||||
gfx.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
break;
|
||||||
//gfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
|
|
||||||
|
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
|
#endregion
|
||||||
|
|
||||||
#region MeasureTextExtents
|
#region MeasureTextExtents
|
||||||
|
|
||||||
TextExtents MeasureTextExtents(TextBlock block)
|
TextExtents MeasureTextExtents(TextBlock block, TextQuality quality)
|
||||||
{
|
{
|
||||||
// Todo: Parse layout options:
|
// Todo: Parse layout options:
|
||||||
//StringFormat format = default_string_format;
|
//StringFormat format = default_string_format;
|
||||||
|
@ -199,7 +200,7 @@ namespace OpenTK.Graphics.Text
|
||||||
if (block.Bounds == SizeF.Empty)
|
if (block.Bounds == SizeF.Empty)
|
||||||
rect.Size = MaximumGraphicsClipSize;
|
rect.Size = MaximumGraphicsClipSize;
|
||||||
|
|
||||||
SetTextRenderingOptions(graphics, block.Font);
|
SetTextRenderingOptions(graphics, block.Font, quality);
|
||||||
|
|
||||||
IntPtr native_graphics = GdiPlus.GetNativeGraphics(graphics);
|
IntPtr native_graphics = GdiPlus.GetNativeGraphics(graphics);
|
||||||
IntPtr native_font = GdiPlus.GetNativeFont(block.Font);
|
IntPtr native_font = GdiPlus.GetNativeFont(block.Font);
|
||||||
|
@ -239,6 +240,8 @@ namespace OpenTK.Graphics.Text
|
||||||
IEnumerable<RectangleF> MeasureGlyphExtents(string text, int height,
|
IEnumerable<RectangleF> MeasureGlyphExtents(string text, int height,
|
||||||
RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format)
|
RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format)
|
||||||
{
|
{
|
||||||
|
measured_glyphs.Clear();
|
||||||
|
|
||||||
RectangleF rect = new RectangleF();
|
RectangleF rect = new RectangleF();
|
||||||
int current = 0;
|
int current = 0;
|
||||||
while (current < text.Length)
|
while (current < text.Length)
|
||||||
|
@ -277,11 +280,14 @@ namespace OpenTK.Graphics.Text
|
||||||
|
|
||||||
rect.Y += height;
|
rect.Y += height;
|
||||||
|
|
||||||
yield return rect;
|
//yield return rect;
|
||||||
|
measured_glyphs.Add(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
current += num_characters;
|
current += num_characters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return measured_glyphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -31,41 +31,54 @@ using System.Drawing;
|
||||||
|
|
||||||
namespace OpenTK.Graphics.Text
|
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<T> : GlyphCache where T : Texture2D
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
IGlyphRasterizer rasterizer;
|
List<GlyphSheet<T>> sheets = new List<GlyphSheet<T>>();
|
||||||
List<GlyphSheet> sheets = new List<GlyphSheet>();
|
|
||||||
Bitmap bmp = new Bitmap(32, 32);
|
Bitmap bmp = new Bitmap(32, 32);
|
||||||
|
|
||||||
Dictionary<Glyph, CachedGlyphInfo> cached_glyphs = new Dictionary<Glyph, CachedGlyphInfo>();
|
Dictionary<Glyph, CachedGlyphInfo> cached_glyphs = new Dictionary<Glyph, CachedGlyphInfo>();
|
||||||
|
|
||||||
|
const int SheetWidth = 512, SheetHeight = 512;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
public GlyphCache(IGlyphRasterizer rasterizer)
|
public GlyphCache()
|
||||||
{
|
{
|
||||||
if (rasterizer == null)
|
sheets.Add(new GlyphSheet<T>(SheetWidth, SheetHeight));
|
||||||
throw new ArgumentNullException("rasterizer");
|
|
||||||
|
|
||||||
this.rasterizer = rasterizer;
|
|
||||||
sheets.Add(new GlyphSheet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IGlyphCache Members
|
#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;
|
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);
|
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||||||
foreach (GlyphSheet sheet in sheets)
|
foreach (GlyphSheet<T> sheet in sheets)
|
||||||
{
|
{
|
||||||
inserted = InsertGlyph(glyph, bmp, rect, sheet);
|
inserted = InsertGlyph(glyph, bmp, rect, sheet);
|
||||||
if (inserted)
|
if (inserted)
|
||||||
|
@ -74,19 +87,19 @@ namespace OpenTK.Graphics.Text
|
||||||
|
|
||||||
if (!inserted)
|
if (!inserted)
|
||||||
{
|
{
|
||||||
GlyphSheet sheet = new GlyphSheet();
|
GlyphSheet<T> sheet = new GlyphSheet<T>(SheetWidth, SheetHeight);
|
||||||
sheets.Add(sheet);
|
sheets.Add(sheet);
|
||||||
InsertGlyph(glyph, bmp, rect, sheet);
|
InsertGlyph(glyph, bmp, rect, sheet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(Glyph glyph)
|
public override bool Contains(Glyph glyph)
|
||||||
{
|
{
|
||||||
return cached_glyphs.ContainsKey(glyph);
|
return cached_glyphs.ContainsKey(glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedGlyphInfo this[Glyph glyph]
|
public override CachedGlyphInfo this[Glyph glyph]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -99,7 +112,7 @@ namespace OpenTK.Graphics.Text
|
||||||
#region Private Members
|
#region Private Members
|
||||||
|
|
||||||
// Asks the packer for an empty space and writes the glyph there.
|
// 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<T> sheet)
|
||||||
{
|
{
|
||||||
Rectangle target = new Rectangle();
|
Rectangle target = new Rectangle();
|
||||||
if (!sheet.Packer.TryAdd(source, out target))
|
if (!sheet.Packer.TryAdd(source, out target))
|
||||||
|
|
|
@ -32,35 +32,35 @@ using System.Drawing;
|
||||||
|
|
||||||
namespace OpenTK.Graphics.Text
|
namespace OpenTK.Graphics.Text
|
||||||
{
|
{
|
||||||
class GlyphSheet
|
class GlyphSheet<T> where T : Texture2D
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
//AlphaTexture2D texture;
|
readonly T texture;
|
||||||
RgbaTexture2D texture = new RgbaTexture2D(512, 512);
|
readonly GlyphPacker packer;
|
||||||
GlyphPacker packer = new GlyphPacker(512, 512);
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#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
|
#endregion
|
||||||
|
|
||||||
#region Public Members
|
#region Public Members
|
||||||
|
|
||||||
public Texture2D Texture
|
public T Texture
|
||||||
{
|
{
|
||||||
get { return texture; }
|
get { return texture; }
|
||||||
private set { texture = (RgbaTexture2D)value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlyphPacker Packer
|
public GlyphPacker Packer
|
||||||
{
|
{
|
||||||
get { return packer; }
|
get { return packer; }
|
||||||
private set { packer = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace OpenTK.Graphics.Text
|
||||||
{
|
{
|
||||||
interface IGlyphCache
|
interface IGlyphCache
|
||||||
{
|
{
|
||||||
void Add(Glyph glyph);
|
void Add(Glyph glyph, IGlyphRasterizer rasterizer, TextQuality quality);
|
||||||
bool Contains(Glyph glyph);
|
bool Contains(Glyph glyph);
|
||||||
CachedGlyphInfo this[Glyph glyph] { get; }
|
CachedGlyphInfo this[Glyph glyph] { get; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,8 @@ namespace OpenTK.Graphics.Text
|
||||||
interface IGlyphRasterizer
|
interface IGlyphRasterizer
|
||||||
{
|
{
|
||||||
Bitmap Rasterize(Glyph glyph);
|
Bitmap Rasterize(Glyph glyph);
|
||||||
TextExtents MeasureText(TextBlock block, PointF location);
|
Bitmap Rasterize(Glyph glyph, TextQuality quality);
|
||||||
void Rasterize(Glyph glyph, ref Bitmap bmp, out Rectangle rect);
|
TextExtents MeasureText(TextBlock block);
|
||||||
|
TextExtents MeasureText(TextBlock block, TextQuality quality);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace OpenTK.Graphics.Text
|
||||||
{
|
{
|
||||||
interface ITextOutputProvider
|
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 Begin();
|
||||||
void End();
|
void End();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace OpenTK.Graphics.Text
|
||||||
protected RectangleF text_extents;
|
protected RectangleF text_extents;
|
||||||
protected List<RectangleF> glyph_extents = new List<RectangleF>();
|
protected List<RectangleF> glyph_extents = new List<RectangleF>();
|
||||||
|
|
||||||
|
public static readonly TextExtents Empty = new TextExtents();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
14
Source/Utilities/Graphics/Text/TextQuality.cs
Normal file
14
Source/Utilities/Graphics/Text/TextQuality.cs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,9 +30,9 @@ namespace OpenTK.Graphics
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
GlyphCache glyph_cache;
|
|
||||||
IGlyphRasterizer glyph_rasterizer;
|
IGlyphRasterizer glyph_rasterizer;
|
||||||
ITextOutputProvider text_output;
|
ITextOutputProvider text_output;
|
||||||
|
TextQuality text_quality;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -42,21 +42,16 @@ namespace OpenTK.Graphics
|
||||||
/// Constructs a new TextPrinter object.
|
/// Constructs a new TextPrinter object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TextPrinter()
|
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_rasterizer = rasterizer;
|
||||||
glyph_cache = new GlyphCache(rasterizer);
|
|
||||||
text_output = output;
|
text_output = output;
|
||||||
|
text_quality = quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -71,7 +66,7 @@ namespace OpenTK.Graphics
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
public void Begin()
|
public void Begin()
|
||||||
{
|
{
|
||||||
text_output.Begin();
|
TextOutput.Begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -84,7 +79,7 @@ namespace OpenTK.Graphics
|
||||||
[Obsolete]
|
[Obsolete]
|
||||||
public void End()
|
public void End()
|
||||||
{
|
{
|
||||||
text_output.End();
|
TextOutput.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -93,25 +88,20 @@ namespace OpenTK.Graphics
|
||||||
|
|
||||||
public void Print(string text, Font font, Color color)
|
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;
|
return;
|
||||||
|
|
||||||
if (font == null)
|
text_output.Print(new TextBlock(text, font, options, size), color, Rasterizer);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -120,17 +110,30 @@ namespace OpenTK.Graphics
|
||||||
|
|
||||||
public TextExtents Measure(string text, Font font)
|
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
|
#endregion
|
||||||
|
@ -158,5 +161,48 @@ namespace OpenTK.Graphics
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue