我正在开发一个项目,可以生成包含相当复杂的数学和科学公式的PDF.文本以Times New Roman呈现,它具有非常好的Unicode覆盖范围,但不完整.我们有一个系统来交换一个更unicode完整的字体,用于TNR中没有字形的代码点(就像大多数"陌生人"的数学符号一样),但我似乎找不到查询的方法*.ttf文件以查看是否存在给定的字形.到目前为止,我只是硬编码了一个存在代码点的查找表,但我更喜欢自动解决方案.
我在ASP.net下的Web系统中使用VB.Net,但是可以理解任何编程语言/环境中的解决方案.
编辑:win32解决方案看起来很棒,但我试图解决的具体情况是在ASP.Net网络系统中.有没有办法在不将Windows API dll包含到我的网站中的情况下执行此操作?
这是使用c#和windows api的传递.
[DllImport("gdi32.dll")] public static extern uint GetFontUnicodeRanges(IntPtr hdc, IntPtr lpgs); [DllImport("gdi32.dll")] public extern static IntPtr SelectObject(IntPtr hDC, IntPtr hObject); public struct FontRange { public UInt16 Low; public UInt16 High; } public ListGetUnicodeRangesForFont(Font font) { Graphics g = Graphics.FromHwnd(IntPtr.Zero); IntPtr hdc = g.GetHdc(); IntPtr hFont = font.ToHfont(); IntPtr old = SelectObject(hdc, hFont); uint size = GetFontUnicodeRanges(hdc, IntPtr.Zero); IntPtr glyphSet = Marshal.AllocHGlobal((int)size); GetFontUnicodeRanges(hdc, glyphSet); List fontRanges = new List (); int count = Marshal.ReadInt32(glyphSet, 12); for (int i = 0; i < count; i++) { FontRange range = new FontRange(); range.Low = (UInt16)Marshal.ReadInt16(glyphSet, 16 + i * 4); range.High = (UInt16)(range.Low + Marshal.ReadInt16(glyphSet, 18 + i * 4) - 1); fontRanges.Add(range); } SelectObject(hdc, old); Marshal.FreeHGlobal(glyphSet); g.ReleaseHdc(hdc); g.Dispose(); return fontRanges; } public bool CheckIfCharInFont(char character, Font font) { UInt16 intval = Convert.ToUInt16(character); List ranges = GetUnicodeRangesForFont(font); bool isCharacterPresent = false; foreach (FontRange range in ranges) { if (intval >= range.Low && intval <= range.High) { isCharacterPresent = true; break; } } return isCharacterPresent; }
然后,给出一个char toCheck你要检查和一个Font theFont来测试它...
if (!CheckIfCharInFont(toCheck, theFont) { // not present }
使用VB.Net的相同代码
_ Public Shared Function GetFontUnicodeRanges(ByVal hds As IntPtr, ByVal lpgs As IntPtr) As UInteger End Function _ 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