Custom Unicode Character Map / Determining Codepoint range in Font

Hi. I’m trying to create a custom Character Map window like the OSX Character Palette and MS Word Insert Symbol window etc but am having an issue with certain unicode characters that are not displaying correctly because the font used has no glyph for them.

I would like to eliminate these characters from the character map so the user cannot see the weird block sign or empty space.

Is there a way to find out if a font has a particular UTF8 codepoint in its character glyph set through basic code or cross-platform declares?

Thanks,

Denise

Denise. I followed this post because I was curious about the answer also. With 32 views and no replies, I think the answer must be “no”. I present a pallette from which the user can select a UTF8 set and see the available chars. for that set. I was working under the assumption that if the user saw an odd char there, they would not make that selection.

There is unfortunately no way to get such information from the system. The only way to know if a character is assigned is placed in the font file itself, so to fetch that information would require going through the installed font files and inspect them. Given the different standards used, it can be extremely challenging.

More on fonts internal structure can be found at http://microsoft.com/typography

Hi Guys. Thanks for the replies. I found a couple of articles that might shed some light on the issue and the possibility of using declares. At least on Windows:

http://stackoverflow.com/questions/103725/is-there-a-way-to-programatically-determine-if-a-font-file-has-a-specific-unicod

http://stackoverflow.com/questions/5274311/checking-if-certain-characters-are-supported-by-a-font

Would be great to get this code converted into Xojo to test it and to know if there is a Mac OS X equivalent. Any ideas?

Do you really care about whether a specific font has the glyph, or do you just care that some font has the glyph and it can be rendered?

I would like to eliminate a specific glyph from the character map if it cannot be rendered in the current font.

Well, ‘rendered in the current font’ is a peculiar thing because of font fallbacks. If a font doesn’t have a character, functions like Graphics.DrawString will check if any font does and use the glyphs from that font.

If you’re really after a whether or not a specific font has supports a Unicode code point on OS X, I’d try CTFontCreateWithName + CTFontCopyCharacterSet + CFCharacterSetIsLongCharacterMember.

[quote=61377:@Denise Adams]I found a couple of articles that might shed some light on the issue and the possibility of using declares. At least on Windows:

http://stackoverflow.com/questions/103725/is-there-a-way-to-programatically-determine-if-a-font-file-has-a-specific-unicod [/quote]

The VB.Net example there should be transposable into Xojo. This kind of feature could be a great asset for Windows font use.

I do not have the mastery of Declares required to do that, though, but others on this forum may be able to help. Here is the VB.NET Code :

[code]<DllImport(“gdi32.dll”)> _
Public Shared Function GetFontUnicodeRanges(ByVal hds As IntPtr, ByVal lpgs As IntPtr) As UInteger
End Function

<DllImport(“gdi32.dll”)> _
Public Shared Function SelectObject(ByVal hDc As IntPtr, ByVal hObject As IntPtr) As IntPtr
End Function

Public Structure FontRange
Public Low As UInt16
Public High As UInt16
End Structure

Public Function GetUnicodeRangesForFont(ByVal font As Font) As List(Of FontRange)
Dim g As Graphics
Dim hdc, hFont, old, glyphSet As IntPtr
Dim size As UInteger
Dim fontRanges As List(Of FontRange)
Dim count As Integer

g = Graphics.FromHwnd(IntPtr.Zero)
hdc = g.GetHdc()
hFont = font.ToHfont()
old = SelectObject(hdc, hFont)
size = GetFontUnicodeRanges(hdc, IntPtr.Zero)
glyphSet = Marshal.AllocHGlobal(CInt(size))
GetFontUnicodeRanges(hdc, glyphSet)
fontRanges = New List(Of FontRange)
count = Marshal.ReadInt32(glyphSet, 12)

For i = 0 To count - 1
	Dim range As FontRange = New FontRange
	range.Low = Marshal.ReadInt16(glyphSet, 16 + (i * 4))
	range.High = range.Low + Marshal.ReadInt16(glyphSet, 18 + (i * 4)) - 1
	fontRanges.Add(range)
Next

SelectObject(hdc, old)
Marshal.FreeHGlobal(glyphSet)
g.ReleaseHdc(hdc)
g.Dispose()

Return fontRanges

End Function

Public Function CheckIfCharInFont(ByVal character As Char, ByVal font As Font) As Boolean
Dim intval As UInt16 = Convert.ToUInt16(character)
Dim ranges As List(Of FontRange) = GetUnicodeRangesForFont(font)
Dim isCharacterPresent As Boolean = False

For Each range In ranges
	If intval >= range.Low And intval <= range.High Then
		isCharacterPresent = True
		Exit For
	End If
Next range
Return isCharacterPresent

End Function[/code]

Joe, thanks for the OS X info links and Michael thanks for the VB.net code. I also don’t have the know-how to transpose all this into Xojo but will research further and post back if I come up with anything else useful. If anyone does know how to get this working in Xojo that would be great since as Michael said, this kind of font code would be an extremely useful cross-platform utility. Thanks again!