I\'m working on a project that generates PDFs that can contain fairly complex math and science formulas. The text is rendered in Times New Roman, which has pretty good Unic
Scott's answer is good. Here is another approach that is probably faster if checking just a couple of strings per font (in our case 1 string per font). But probably slower if you are using one font to check a ton of text.
[DllImport("gdi32.dll", EntryPoint = "CreateDC", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateDC(string lpszDriver, string lpszDeviceName, string lpszOutput, IntPtr devMode);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool DeleteDC(IntPtr hdc);
[DllImport("Gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("Gdi32.dll", CharSet = CharSet.Unicode)]
private static extern int GetGlyphIndices(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string lpstr, int c,
Int16[] pgi, int fl);
///
/// Returns true if the passed in string can be displayed using the passed in fontname. It checks the font to
/// see if it has glyphs for all the chars in the string.
///
/// The name of the font to check.
/// The text to check for glyphs of.
///
public static bool CanDisplayString(string fontName, string text)
{
try
{
IntPtr hdc = CreateDC("DISPLAY", null, null, IntPtr.Zero);
if (hdc != IntPtr.Zero)
{
using (Font font = new Font(new FontFamily(fontName), 12, FontStyle.Regular, GraphicsUnit.Point))
{
SelectObject(hdc, font.ToHfont());
int count = text.Length;
Int16[] rtcode = new Int16[count];
GetGlyphIndices(hdc, text, count, rtcode, 0xffff);
DeleteDC(hdc);
foreach (Int16 code in rtcode)
if (code == 0)
return false;
}
}
}
catch (Exception)
{
// nada - return true
Trap.trap();
}
return true;
}