Implemented MeasureCharacterRanges function using the new GdiPlus bindings.
This commit is contained in:
parent
0a8f1a9c6a
commit
314bec1c66
1 changed files with 113 additions and 9 deletions
|
@ -25,7 +25,7 @@ namespace OpenTK.Graphics
|
||||||
public class TextureFont : IFont
|
public class TextureFont : IFont
|
||||||
{
|
{
|
||||||
Font font;
|
Font font;
|
||||||
Dictionary<char, Box2> loaded_glyphs = new Dictionary<char, Box2>(64);
|
Dictionary<char, RectangleF> loaded_glyphs = new Dictionary<char, RectangleF>(64);
|
||||||
|
|
||||||
Bitmap bmp;
|
Bitmap bmp;
|
||||||
Graphics gfx;
|
Graphics gfx;
|
||||||
|
@ -80,7 +80,7 @@ namespace OpenTK.Graphics
|
||||||
/// <param name="glyphs">The glyphs to prepare for rendering.</param>
|
/// <param name="glyphs">The glyphs to prepare for rendering.</param>
|
||||||
public void LoadGlyphs(string glyphs)
|
public void LoadGlyphs(string glyphs)
|
||||||
{
|
{
|
||||||
Box2 rect = new Box2();
|
RectangleF rect = new RectangleF();
|
||||||
foreach (char c in glyphs)
|
foreach (char c in glyphs)
|
||||||
{
|
{
|
||||||
if (!loaded_glyphs.ContainsKey(c))
|
if (!loaded_glyphs.ContainsKey(c))
|
||||||
|
@ -98,14 +98,14 @@ namespace OpenTK.Graphics
|
||||||
/// <param name="glyphs">The glyph to prepare for rendering.</param>
|
/// <param name="glyphs">The glyph to prepare for rendering.</param>
|
||||||
public void LoadGlyph(char glyph)
|
public void LoadGlyph(char glyph)
|
||||||
{
|
{
|
||||||
Box2 rect = new Box2();
|
RectangleF rect = new RectangleF();
|
||||||
if (!loaded_glyphs.ContainsKey(glyph))
|
if (!loaded_glyphs.ContainsKey(glyph))
|
||||||
LoadGlyph(glyph, out rect);
|
LoadGlyph(glyph, out rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region public bool GlyphData(char glyph, out float width, out float height, out Box2 textureRectangle, out int texture)
|
#region public bool GlyphData(char glyph, out float width, out float height, out RectangleF textureRectangle, out int texture)
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the characteristics of a loaded glyph.
|
/// Returns the characteristics of a loaded glyph.
|
||||||
|
@ -117,7 +117,7 @@ namespace OpenTK.Graphics
|
||||||
/// <param name="texture">The handle to the texture that contains this glyph.</param>
|
/// <param name="texture">The handle to the texture that contains this glyph.</param>
|
||||||
/// <returns>True if the glyph has been loaded, false otherwise.</returns>
|
/// <returns>True if the glyph has been loaded, false otherwise.</returns>
|
||||||
/// <seealso cref="LoadGlyphs"/>
|
/// <seealso cref="LoadGlyphs"/>
|
||||||
public bool GlyphData(char glyph, out float width, out float height, out Box2 textureRectangle, out int texture)
|
public bool GlyphData(char glyph, out float width, out float height, out RectangleF textureRectangle, out int texture)
|
||||||
{
|
{
|
||||||
if (loaded_glyphs.TryGetValue(glyph, out textureRectangle))
|
if (loaded_glyphs.TryGetValue(glyph, out textureRectangle))
|
||||||
{
|
{
|
||||||
|
@ -164,16 +164,27 @@ namespace OpenTK.Graphics
|
||||||
/// <param name="str">The string to measure.</param>
|
/// <param name="str">The string to measure.</param>
|
||||||
/// <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="addSpace">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>
|
||||||
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;
|
||||||
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
|
//format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
|
||||||
|
|
||||||
System.Drawing.SizeF size = gfx.MeasureString(str, font, 16384, format);
|
System.Drawing.SizeF size = gfx.MeasureString(str, font, 16384, format);
|
||||||
height = size.Height;
|
height = size.Height;
|
||||||
width = size.Width;
|
width = size.Width;
|
||||||
|
|
||||||
|
//width = height = 0;
|
||||||
|
|
||||||
|
//RectangleF rect = new RectangleF(0, 0, 0, 0);
|
||||||
|
//ICollection<RectangleF> ranges = new List<RectangleF>();
|
||||||
|
//MeasureCharacterRanges(gfx, str, font, ref rect, format, ref ranges);
|
||||||
|
//foreach (RectangleF range in ranges)
|
||||||
|
//{
|
||||||
|
// width += range.Width;
|
||||||
|
// height = range.Height > height ?range.Height : height;
|
||||||
|
//}
|
||||||
|
|
||||||
// width = 0;
|
// width = 0;
|
||||||
// height = 0;
|
// height = 0;
|
||||||
// int i = 0;
|
// int i = 0;
|
||||||
|
@ -208,10 +219,103 @@ namespace OpenTK.Graphics
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region public void MeasureCharacterRanges(string text, ref ICollection<RectangleF> ranges)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Measures the individual character positions for the specified string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The string to measure.</param>
|
||||||
|
/// <param name="ranges">An ICollection of RectangleF structures, containing the positions of individual characters.</param>
|
||||||
|
public void MeasureCharacterRanges(string text, ref ICollection<RectangleF> ranges)
|
||||||
|
{
|
||||||
|
MeasureCharacterRanges(text, false, ref ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region public void MeasureCharacterRanges(string text, bool accountForOverhangs, ref ICollection<RectangleF> ranges)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Measures the individual character positions for the specified string.
|
||||||
|
/// </summary>
|
||||||
|
/// <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="ranges">An ICollection of RectangleF structures, containing the positions of individual characters.</param>
|
||||||
|
public void MeasureCharacterRanges(string text, bool accountForOverhangs, ref ICollection<RectangleF> ranges)
|
||||||
|
{
|
||||||
|
System.Drawing.StringFormat format = accountForOverhangs ? System.Drawing.StringFormat.GenericDefault : System.Drawing.StringFormat.GenericTypographic;
|
||||||
|
RectangleF rect = new RectangleF(0, 0, gfx.ClipBounds.Width, gfx.ClipBounds.Height);
|
||||||
|
MeasureCharacterRanges(text, ref rect, format, ref ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region --- Private Methods ---
|
#region --- Private Methods ---
|
||||||
|
|
||||||
|
#region void MeasureCharacterRanges(string text, ref RectangleF layoutRect, StringFormat format, ref ICollection<RectangleF> ranges)
|
||||||
|
|
||||||
|
void MeasureCharacterRanges(string text, ref RectangleF layoutRect, StringFormat format, ref ICollection<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;
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(text))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (font == null) throw new ArgumentNullException("font");
|
||||||
|
if (format == null) throw new ArgumentNullException("format");
|
||||||
|
|
||||||
|
IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges];
|
||||||
|
CharacterRange[] characterRanges = new CharacterRange[GdiPlus.MaxMeasurableCharacterRanges];
|
||||||
|
|
||||||
|
for (int i = 0; i < text.Length; i += GdiPlus.MaxMeasurableCharacterRanges)
|
||||||
|
{
|
||||||
|
int num_characters = text.Length - i > GdiPlus.MaxMeasurableCharacterRanges ? GdiPlus.MaxMeasurableCharacterRanges : text.Length - i;
|
||||||
|
|
||||||
|
for (int j = 0; j < num_characters; j++)
|
||||||
|
{
|
||||||
|
characterRanges[j] = new CharacterRange(i + j, 1);
|
||||||
|
|
||||||
|
IntPtr region;
|
||||||
|
status = GdiPlus.CreateRegion(out region);
|
||||||
|
regions[j] = region;
|
||||||
|
if (status != 0)
|
||||||
|
Debug.Print("GDI+ error: {0}", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
CharacterRange[] a = (CharacterRange[])characterRanges.Clone();
|
||||||
|
Array.Resize(ref a, num_characters);
|
||||||
|
format.SetMeasurableCharacterRanges(a);
|
||||||
|
|
||||||
|
IntPtr native_graphics = GdiPlus.GetNativeGraphics(gfx);
|
||||||
|
IntPtr native_font = GdiPlus.GetNativeFont(font);
|
||||||
|
IntPtr native_string_format = GdiPlus.GetNativeStringFormat(format);
|
||||||
|
|
||||||
|
status = GdiPlus.MeasureCharacterRanges(new HandleRef(gfx, native_graphics), text, text.Length,
|
||||||
|
new HandleRef(font, native_font), ref layoutRect,
|
||||||
|
new HandleRef(format, (format == null) ? IntPtr.Zero : native_string_format),
|
||||||
|
num_characters, regions);
|
||||||
|
|
||||||
|
for (int j = 0; j < num_characters; j++)
|
||||||
|
{
|
||||||
|
RectangleF rect = new RectangleF();
|
||||||
|
status = GdiPlus.GetRegionBounds(regions[j], new HandleRef(gfx, GdiPlus.GetNativeGraphics(gfx)), ref rect);
|
||||||
|
|
||||||
|
ranges.Add(rect);
|
||||||
|
|
||||||
|
status = GdiPlus.DeleteRegion(regions[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region private void PrepareTexturePacker()
|
#region private void PrepareTexturePacker()
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -250,7 +354,7 @@ namespace OpenTK.Graphics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="c">The character of the glyph.</param>
|
/// <param name="c">The character of the glyph.</param>
|
||||||
/// <param name="rectangle">An OpenTK.Math.Box2 that will hold the buffer for this glyph.</param>
|
/// <param name="rectangle">An OpenTK.Math.Box2 that will hold the buffer for this glyph.</param>
|
||||||
private void LoadGlyph(char c, out Box2 rectangle)
|
private void LoadGlyph(char c, out RectangleF rectangle)
|
||||||
{
|
{
|
||||||
if (pack == null)
|
if (pack == null)
|
||||||
PrepareTexturePacker();
|
PrepareTexturePacker();
|
||||||
|
@ -299,7 +403,7 @@ namespace OpenTK.Graphics
|
||||||
}
|
}
|
||||||
bmp.UnlockBits(bitmap_data);
|
bmp.UnlockBits(bitmap_data);
|
||||||
|
|
||||||
rectangle = new Box2(
|
rectangle = RectangleF.FromLTRB(
|
||||||
rect.Left / (float)texture_width,
|
rect.Left / (float)texture_width,
|
||||||
rect.Top / (float)texture_height,
|
rect.Top / (float)texture_height,
|
||||||
rect.Right / (float)texture_width,
|
rect.Right / (float)texture_width,
|
||||||
|
|
Loading…
Reference in a new issue