|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace aspnet_TextTruncator
{
public static class TextTruncator
{
// Private Properties
//
private static Dictionary<string, int[]> _fontWidthDic;
private static Dictionary<string, int[]> FontWidthDic
{
get
{
if (_fontWidthDic == null)
{
_fontWidthDic = new Dictionary<string, int[]>();
}
return _fontWidthDic;
}
}
//
// Public Methods
//
public static string TruncateText(string text, int textMaxWidth, string fontName, int fontSizeInPixels)
{
return TruncateText(text, textMaxWidth, fontName, fontSizeInPixels, false);
}
public static string TruncateText(string text, int textMaxWidth, string fontName, int fontSizeInPixels, bool isFontBold)
{
if (string.IsNullOrEmpty(text))
return text;
// Check
//
if (textMaxWidth < 1 ||
string.IsNullOrEmpty(fontName) ||
fontSizeInPixels < 1)
{
throw new ArgumentException();
}
int[] fontWidthArray = GetFontWidthArray(fontName, fontSizeInPixels, isFontBold);
int ellipsisWidth = fontWidthArray['.'] * 3;
int totalCharCount = text.Length;
int textWidth = 0;
int charIndex = 0;
for (int i = 0; i < totalCharCount; i++)
{
textWidth += fontWidthArray[text[i]];
if (textWidth > textMaxWidth)
{
return text.Substring(0, charIndex) + "...";
}
else if (textWidth + ellipsisWidth <= textMaxWidth)
{
charIndex = i;
}
}
return text;
}
//
// Private Methods
//
private static int[] GetFontWidthArray(string fontName, int fontSizeInPixels, bool isFontBold)
{
string fontEntryName = fontName.ToLower() + "_" + fontSizeInPixels.ToString() + "px" + (isFontBold ? "_bold" : "");
int[] fontWidthArray;
if (!FontWidthDic.TryGetValue(fontEntryName, out fontWidthArray))
{
fontWidthArray = CreateFontWidthArray(new Font(fontName, fontSizeInPixels, isFontBold ? FontStyle.Bold : FontStyle.Regular, GraphicsUnit.Pixel));
FontWidthDic[fontEntryName] = fontWidthArray;
}
return fontWidthArray;
}
private static int[] CreateFontWidthArray(Font font)
{
int[] fontWidthArray = new int[256];
for (int i = 32; i < 256; i++)
{
char c = (char)i;
fontWidthArray[i] = IsIllegalCharacter(c, false) ? 0 : GetCharWidth(c, font);
}
return fontWidthArray;
}
private static int GetCharWidth(char c, Font font)
{
// Note1: For typography related reasons, TextRenderer.MeasureText() doesn't return the correct
// width of the character in pixels, hence the need to use this hack (with the '<' & '>'
// characters and the subtraction). Note that <' and '>' were chosen randomly, other characters
// can be used.
//
// Note2: As the TextRenderer class is intended to be used with Windows Forms Applications, it has a
// special use for the ampersand character (used for Mnemonics). Therefore, we need to check for the
// ampersand character and replace it with '&&' to escape it (TextRenderer.MeasureText() will treat
// it as one ampersand character)
//
return
TextRenderer.MeasureText("<" + (c == '&' ? "&&" : c.ToString()) + ">", font).Width -
TextRenderer.MeasureText("<>", font).Width;
}
private static bool ContainsIllegalCharacters(string text, bool excludeLineBreaks)
{
if (!string.IsNullOrEmpty(text))
{
foreach (char c in text)
{
if (IsIllegalCharacter(c, excludeLineBreaks))
return true;
}
}
return false;
}
private static bool IsIllegalCharacter(char c, bool excludeLineBreaks)
{
// See the Windows-1252 encoding (we use ISO-8859-1, but all browsers, or at least
// IE, FF, Opera, Chrome and Safari, interpret ISO-8859-1 as Windows-1252).
// For more information, see http://en.wikipedia.org/wiki/ISO/IEC_8859-1#ISO-8859-1_and_Windows-1252_confusion
//
return
(c < 32 && (!excludeLineBreaks || c != '\n')) ||
c > 255 ||
c == 127 ||
c == 129 ||
c == 141 ||
c == 143 ||
c == 144 ||
c == 157;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
My name is Waleed Eissa and I'm a software developer from Cairo, Egypt. I spent 7 years developing software for the banking industry, but has changed focus in recent years to Web development. I specialize in Microsoft technologies, esp. ASP.NET and C#, and am passionate about everything web. My main interests are user experience design (UX), performance tuning and scalability.
Website:
http://www.waleedeissa.com
Blog:
http://waldev.blogspot.com