有没有一种方法以编程方式确定是否字体文件有一个特定的UNI code雕文? [英] Is there a way to programatically determine if a font file has a specific Unicode Glyph?

查看:240
本文介绍了有没有一种方法以编程方式确定是否字体文件有一个特定的UNI code雕文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作产生可以包含相当复杂的数学和科学公式PDF文件的项目。该文本是宋体,其中有pretty良好的Uni code覆盖,但不完整呈现。我们有一个系统,在code点多单code完整的字体没有在TNR字形交换(像极了陌生人的数学符号),但我不能似乎找到一种方法来查询* .TTF文件,看是否有给定的字形是present。到目前为止,我只是硬codeD查找表,其中code点present,但我更preFER自动解决方案。

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 Unicode coverage, but not complete. We have a system in place to swap in a more unicode complete font for code points that don't have a glyph in TNR (like most of the "stranger" math symbols,) but I can't seem to find a way to query the *.ttf file to see if a given glyph is present. So far, I've just hard-coded a lookup table of which code points are present, but I'd much prefer an automatic solution.

我在ASP.net下一个网络系统使用VB.Net,但在任何编程语言/环境的解决方案将是AP preciated。谢谢!

I'm using VB.Net in a web system under ASP.net, but solutions in any programming language / environment would be appreciated. Thanks!

编辑:在Win32解决方案看起来很好,但我试图解决具体案件是一个ASP.Net Web系统。有没有办法做到这一点,而不包括Windows API的dll文件到我的网站?

The win32 solution looks excellent, but the specific case I'm trying to solve is in an ASP.Net web system. Is there a way to do this without including the windows API dlls into my web site?

推荐答案

下面使用C#和Windows API的是一通吧。

Here's a pass at it using c# and the 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 List<FontRange> GetUnicodeRangesForFont(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<FontRange> fontRanges = new List<FontRange>();
    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<FontRange> 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和字体theFont来测试它反对...

Then, given a char toCheck that you want to check and a Font theFont to test it against...

if (!CheckIfCharInFont(toCheck, theFont) {
    // not present
}

使用VB.Net相同code

Same code using VB.Net

<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

这篇关于有没有一种方法以编程方式确定是否字体文件有一个特定的UNI code雕文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆