C#: Check for unsupported characters/glyphs in a font
Asked Answered
S

1

4

I am working on a translation software add in (C#, .NET 2.0) which displays translated texts in a emulated device display. I have to check if all translated texts could be displayed with specified fonts (Windows TTF). But I didn't found any way to check a font for unsupported glyphs. Does anyone have an idea?

Thanks

Schellens answered 17/2, 2011 at 6:27 Comment(0)
C
9

Are you limited to .NET 2.0? In .NET 3.0 or higher, there's the GlyphTypeface class, which can load a font file and exposes the CharacterToGlyphMap property, which I believe can do what you want.

In .NET 2.0, I think you'll have to rely on PInvoke. Try something like:

using System.Drawing;
using System.Runtime.InteropServices;

[DllImport("gdi32.dll", EntryPoint = "GetGlyphIndicesW")]
private static extern uint GetGlyphIndices([In] IntPtr hdc, [In] [MarshalAs(UnmanagedType.LPTStr)] string lpsz, int c, [Out] ushort[] pgi, uint fl);

[DllImport("gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

private const uint GGI_MARK_NONEXISTING_GLYPHS = 0x01;

// Create a dummy Graphics object to establish a device context
private Graphics _graphics = Graphics.FromImage(new Bitmap(1, 1));

public bool DoesGlyphExist(char c, Font font)
{
  // Get a device context from the dummy Graphics 
  IntPtr hdc = _graphics.GetHdc();
  ushort[] glyphIndices;

  try {
    IntPtr hfont = font.ToHfont();

    // Load the font into the device context
    SelectObject(hdc, hfont);

    string testString = new string(c, 1);
    glyphIndices = new ushort[testString.Length];

    GetGlyphIndices(hdc, testString, testString.Length, glyphIndices, GGI_MARK_NONEXISTING_GLYPHS);

  } finally {

    // Clean up our mess
    _graphics.ReleaseHdc(hdc);
  }

  // 0xffff is the value returned for a missing glyph
  return (glyphIndices[0] != 0xffff);
}

private void Test()
{
  Font f = new Font("Courier New", 10);

  // Glyph for A is found -- returns true
  System.Diagnostics.Debug.WriteLine(DoesGlyphExist('A', f).ToString()); 

  // Glyph for ಠ is not found -- returns false
  System.Diagnostics.Debug.WriteLine(DoesGlyphExist((char) 0xca0, f).ToString()); 
}
Chancroid answered 22/2, 2011 at 16:56 Comment(4)
Yes, I am limited to .NET 2.0. The other problem is, that your code does the check for each separated character. But in some languages (like arabic) there is no 1 to 1 relationship between a character and a glyph. Some glyphs are depending on surrounding characters and some characters are joined to a single glyph. So I need a method which checks a complete string...Schellens
The GetGlyphIndices function does take a string as a parameter, so you could pass a complete string if you wanted. I only rigged it like this because I thought you were checking individual characters.Chancroid
MSDN says, that GetGlyphIndices() "...attempts to identify a single-glyph representation for each character in the string pointed to by lpstr.". So I´m afraid, that won't work for me. There is a link to "Uniscribe" function, but I did'nt found a simple example...Schellens
Works for me. The only thing I added to the function was a call to DeleteObject(hfont) to prevent an out of memory (resources) exception.Embryology

© 2022 - 2024 — McMap. All rights reserved.