using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace dIRC7.Helpers
{
/* Faster (cached) MeasureStringWidth class
By: Jason James Newland & Ryan Alexander
©2012 KangaSoft Software - All Rights Reserved
*/
#region Fields
internal class FontData
{
public int[] NormalCharacterWidth { get; set; }
public int[] BoldCharacterWidth { get; set; }
public int[] ItalicCharacterWidth { get; set; }
}
#endregion
public sealed class IrcMeasureStringWidth
{
#region Fields
private const TextFormatFlags FormatFlags = TextFormatFlags.Left | TextFormatFlags.NoPrefix | TextFormatFlags.NoPadding | TextFormatFlags.NoClipping;
private static readonly Dictionary Fonts = new Dictionary();
#endregion
#region Public measure string width
public static int MeasureStringWidth(Graphics g, Font font, string text)
{
FontData data;
if (!Fonts.ContainsKey(font))
{
data = new FontData
{
NormalCharacterWidth = BuildLookupList(g, font),
BoldCharacterWidth = BuildLookupList(g, new Font(font, FontStyle.Bold)),
ItalicCharacterWidth = BuildLookupList(g, new Font(font, FontStyle.Italic))
};
Fonts.Add(font, data);
}
else { data = Fonts[font]; }
return MeasureStringWidth(g, text.ToCharArray(), font, data);
}
#endregion
#region Private methods
#region Measure string width overloads
private static int MeasureStringWidth(Graphics g, IList text, Font font, FontData data)
{
if (text == null || text.Count == 0) { return 0; }
return text.Count == 1 ? MeasureStringWidth(g, text[0], font, data) : text.Sum(chr => MeasureStringWidth(g, chr, font, data));
}
private static int MeasureStringWidth(IDeviceContext g, char chr, Font font, FontData data)
{
var chrValue = (int)chr;
if ((font.Bold && font.Italic) || font.Bold)
{
if (chrValue > 255 && data.BoldCharacterWidth[chrValue] == 0)
{
data.BoldCharacterWidth[chrValue] = MeasureString(g, font, chr.ToString());
}
return data.BoldCharacterWidth[chrValue];
}
if (font.Italic)
{
if (chrValue > 255 && data.ItalicCharacterWidth[chrValue] == 0)
{
data.ItalicCharacterWidth[chrValue] = MeasureString(g, font, chr.ToString());
}
return data.ItalicCharacterWidth[chrValue];
}
if (chrValue > 255 && data.NormalCharacterWidth[chrValue] == 0)
{
data.NormalCharacterWidth[chrValue] = MeasureString(g, font, chr.ToString());
}
return data.NormalCharacterWidth[chrValue];
}
#endregion
#region Build main character look-up list
private static int[] BuildLookupList(IDeviceContext g, Font font)
{
var lookUp = new int[char.MaxValue];
for (var i = (char)0; i < (char)256; i++)
{
lookUp[i] = MeasureString(g, font, i.ToString());
}
return lookUp;
}
#endregion
#region GDI measure text string
private static int MeasureString(IDeviceContext g, Font font, string text)
{
return string.IsNullOrEmpty(text) ? 0 : TextRenderer.MeasureText(g, text, font, Size.Empty, FormatFlags).Width;
}
#endregion
#endregion
}
}
|