Renamed MeasureCharacterRanges to MeasureText.

Sped up MeasureText.
Added MeasureText overloads.
Obsoleted MeasureString function.
This commit is contained in:
the_fiddler 2008-06-24 18:27:51 +00:00
parent 26645b1cee
commit f2ac359999

View file

@ -33,15 +33,17 @@ namespace OpenTK.Graphics
static int texture; static int texture;
static TexturePacker<Glyph> pack; static TexturePacker<Glyph> pack;
static int texture_width, texture_height; static int texture_width, texture_height;
static StringFormat default_string_format = StringFormat.GenericTypographic;
static SizeF maximum_graphics_size;
int[] data = new int[256]; // Used to upload glyph buffer to the OpenGL texture. int[] data = new int[256]; // Used to upload the glyph buffer to the OpenGL texture.
object upload_lock = new object(); object upload_lock = new object();
#region --- Constructor --- #region --- Constructor ---
/// <summary> /// <summary>
/// Constructs a new TextureFont object, using the specified System.Drawing.Font. /// Constructs a new TextureFont, using the specified System.Drawing.Font.
/// </summary> /// </summary>
/// <param name="font">The System.Drawing.Font to use.</param> /// <param name="font">The System.Drawing.Font to use.</param>
public TextureFont(Font font) public TextureFont(Font font)
@ -53,6 +55,7 @@ namespace OpenTK.Graphics
bmp = new Bitmap(font.Height * 2, font.Height * 2); bmp = new Bitmap(font.Height * 2, font.Height * 2);
gfx = Graphics.FromImage(bmp); gfx = Graphics.FromImage(bmp);
maximum_graphics_size = gfx.ClipBounds.Size;
// Adjust font rendering mode. Small sizes look blurry without gridfitting, so turn // Adjust font rendering mode. Small sizes look blurry without gridfitting, so turn
// that on. Increasing contrast also seems to help. // that on. Increasing contrast also seems to help.
@ -68,6 +71,25 @@ namespace OpenTK.Graphics
} }
} }
/// <summary>
/// Constructs a new TextureFont, using the specified parameters.
/// </summary>
/// <param name="font">The System.Drawing.FontFamily to use for the typeface.</param>
/// <param name="emSize">The em size to use for the typeface.</param>
public TextureFont(FontFamily family, float emSize)
: this(new Font(family, emSize))
{ }
/// <summary>
/// Constructs a new TextureFont, using the specified parameters.
/// </summary>
/// <param name="font">The System.Drawing.FontFamily to use for the typeface.</param>
/// <param name="emSize">The em size to use for the typeface.</param>
/// <param name="family">The style to use for the typeface.</param>
public TextureFont(FontFamily family, float emSize, FontStyle style)
: this(new Font(family, emSize, style))
{ }
#endregion #endregion
#region --- Public Methods --- #region --- Public Methods ---
@ -82,10 +104,18 @@ namespace OpenTK.Graphics
{ {
RectangleF rect = new RectangleF(); RectangleF rect = new RectangleF();
foreach (char c in glyphs) foreach (char c in glyphs)
{
try
{ {
if (!loaded_glyphs.ContainsKey(c)) if (!loaded_glyphs.ContainsKey(c))
LoadGlyph(c, out rect); LoadGlyph(c, out rect);
} }
catch (Exception e)
{
Debug.Print(e.ToString());
throw;
}
}
} }
#endregion #endregion
@ -165,6 +195,7 @@ namespace OpenTK.Graphics
/// <param name="width">The measured width.</param> /// <param name="width">The measured width.</param>
/// <param name="height">The measured height.</param> /// <param name="height">The measured height.</param>
/// <param name="accountForOverhangs">If true, adds space to account for glyph overhangs. Set to true if you wish to measure a complete string. Set to false if you wish to perform layout on adjacent strings.</param> /// <param name="accountForOverhangs">If true, adds space to account for glyph overhangs. Set to true if you wish to measure a complete string. Set to false if you wish to perform layout on adjacent strings.</param>
[Obsolete("Returns invalid results - use MeasureText() instead")]
public void MeasureString(string str, out float width, out float height, bool accountForOverhangs) public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)
{ {
System.Drawing.StringFormat format = accountForOverhangs ? System.Drawing.StringFormat.GenericDefault : System.Drawing.StringFormat.GenericTypographic; System.Drawing.StringFormat format = accountForOverhangs ? System.Drawing.StringFormat.GenericDefault : System.Drawing.StringFormat.GenericTypographic;
@ -212,6 +243,7 @@ namespace OpenTK.Graphics
/// <param name="width">The measured width.</param> /// <param name="width">The measured width.</param>
/// <param name="height">The measured height.</param> /// <param name="height">The measured height.</param>
/// <seealso cref="public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)"/> /// <seealso cref="public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)"/>
[Obsolete("Returns invalid results - use MeasureText() instead")]
public void MeasureString(string str, out float width, out float height) public void MeasureString(string str, out float width, out float height)
{ {
MeasureString(str, out width, out height, true); MeasureString(str, out width, out height, true);
@ -219,56 +251,75 @@ namespace OpenTK.Graphics
#endregion #endregion
#region public void MeasureCharacterRanges(string text, ref ICollection<RectangleF> ranges) #region public RectangleF MeasureText(string text)
/// <summary> /// <summary>
/// Measures the individual character positions for the specified string. /// Calculates size information for the specified text.
/// </summary> /// </summary>
/// <param name="text">The string to measure.</param> /// <param name="text">The string to measure.</param>
/// <param name="ranges">An ICollection of RectangleF structures, containing the positions of individual characters.</param> /// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public void MeasureCharacterRanges(string text, ref ICollection<RectangleF> ranges) public RectangleF MeasureText(string text)
{ {
MeasureCharacterRanges(text, false, ref ranges); return MeasureText(text, SizeF.Empty, default_string_format, null);
} }
#endregion #endregion
#region public void MeasureCharacterRanges(string text, bool accountForOverhangs, ref ICollection<RectangleF> ranges) #region public RectangleF MeasureText(string text, SizeF bounds)
/// <summary> /// <summary>
/// Measures the individual character positions for the specified string. /// Calculates size information for the specified text.
/// </summary> /// </summary>
/// <param name="text">The string to measure.</param> /// <param name="text">The string to measure.</param>
/// <param name="accountForOverhangs">If true, adds space to account for glyph overhangs. Set to true if you wish to measure a complete string. Set to false if you wish to perform layout on adjacent strings.</param> /// <param name="bounds">A SizeF structure containing the maximum desired width and height of the text. Default is SizeF.Empty.</param>
/// <param name="ranges">An ICollection of RectangleF structures, containing the positions of individual characters.</param> /// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public void MeasureCharacterRanges(string text, bool accountForOverhangs, ref ICollection<RectangleF> ranges) public RectangleF MeasureText(string text, SizeF bounds)
{ {
System.Drawing.StringFormat format = accountForOverhangs ? System.Drawing.StringFormat.GenericDefault : System.Drawing.StringFormat.GenericTypographic; return MeasureText(text, bounds, default_string_format, null);
RectangleF rect = new RectangleF(0, 0, gfx.ClipBounds.Width, gfx.ClipBounds.Height);
MeasureCharacterRanges(text, ref rect, format, ref ranges);
} }
#endregion #endregion
#region public RectangleF MeasureText(string text, SizeF bounds, StringFormat format)
/// <summary>
/// Calculates size information for the specified text.
/// </summary>
/// <param name="text">The string to measure.</param>
/// <param name="bounds">A SizeF structure containing the maximum desired width and height of the text. Pass SizeF.Empty to disable wrapping calculations. A width or height of 0 disables the relevant calculation.</param>
/// <param name="format">A StringFormat object which specifies the measurement format of the string. Pass null to use the default StringFormat (StringFormat.GenericTypographic).</param>
/// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public RectangleF MeasureText(string text, SizeF bounds, StringFormat format)
{
return MeasureText(text, bounds, format, null);
}
#endregion #endregion
#region --- Private Methods --- #region public RectangleF MeasureText(string text, SizeF bounds, StringFormat format, IList<RectangleF> ranges)
#region void MeasureCharacterRanges(string text, ref RectangleF layoutRect, StringFormat format, ref ICollection<RectangleF> ranges) /// <summary>
/// Calculates size information for the specified text.
void MeasureCharacterRanges(string text, ref RectangleF layoutRect, StringFormat format, ref ICollection<RectangleF> ranges) /// </summary>
/// <param name="text">The string to measure.</param>
/// <param name="bounds">A SizeF structure containing the maximum desired width and height of the text. Pass SizeF.Empty to disable wrapping calculations. A width or height of 0 disables the relevant calculation.</param>
/// <param name="format">A StringFormat object which specifies the measurement format of the string. Pass null to use the default StringFormat (StringFormat.GenericTypographic).</param>
/// <param name="ranges">Fills the specified IList of RectangleF structures with position information for individual characters. If this argument is null, these calculations are skipped.</param>
/// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public RectangleF MeasureText(string text, SizeF bounds, StringFormat format, IList<RectangleF> ranges)
{ {
ranges.Clear(); // Hopefully this doesn't trim the collection.
//GPRECTF rect = new GPRECTF(layoutRect);
//rect = new GPRECTF(0, 0, 256, 256);
int status = 0; int status = 0;
if (String.IsNullOrEmpty(text)) RectangleF bounding_box = new RectangleF();
return;
if (font == null) throw new ArgumentNullException("font"); if (String.IsNullOrEmpty(text))
if (format == null) throw new ArgumentNullException("format"); return RectangleF.Empty;
if (bounds == SizeF.Empty)
bounds = maximum_graphics_size;
if (format == null)
format = default_string_format;
IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges]; IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges];
CharacterRange[] characterRanges = new CharacterRange[GdiPlus.MaxMeasurableCharacterRanges]; CharacterRange[] characterRanges = new CharacterRange[GdiPlus.MaxMeasurableCharacterRanges];
@ -295,6 +346,7 @@ namespace OpenTK.Graphics
IntPtr native_graphics = GdiPlus.GetNativeGraphics(gfx); IntPtr native_graphics = GdiPlus.GetNativeGraphics(gfx);
IntPtr native_font = GdiPlus.GetNativeFont(font); IntPtr native_font = GdiPlus.GetNativeFont(font);
IntPtr native_string_format = GdiPlus.GetNativeStringFormat(format); IntPtr native_string_format = GdiPlus.GetNativeStringFormat(format);
RectangleF layoutRect = new RectangleF(PointF.Empty, bounds);
status = GdiPlus.MeasureCharacterRanges(new HandleRef(gfx, native_graphics), text, text.Length, status = GdiPlus.MeasureCharacterRanges(new HandleRef(gfx, native_graphics), text, text.Length,
new HandleRef(font, native_font), ref layoutRect, new HandleRef(font, native_font), ref layoutRect,
@ -303,15 +355,19 @@ namespace OpenTK.Graphics
for (int j = 0; j < num_characters; j++) for (int j = 0; j < num_characters; j++)
{ {
RectangleF rect = new RectangleF(); status = GdiPlus.GetRegionBounds(regions[j], new HandleRef(gfx, GdiPlus.GetNativeGraphics(gfx)), ref bounding_box);
status = GdiPlus.GetRegionBounds(regions[j], new HandleRef(gfx, GdiPlus.GetNativeGraphics(gfx)), ref rect);
ranges.Add(rect); if (ranges != null)
ranges.Add(bounding_box);
status = GdiPlus.DeleteRegion(regions[j]); status = GdiPlus.DeleteRegion(regions[j]);
} }
bounding_box.Size = new SizeF(bounding_box.X + bounding_box.Width, bounding_box.Y + bounding_box.Height);
bounding_box.Location = PointF.Empty;
} }
return bounding_box;
} }
#endregion #endregion