c# - 确定指定字体的确切字形高度

标签 c# fonts .net-1.1 measurement glyph

我已经搜索了很多,尝试了很多,但我找不到合适的解决方案。

我想知道是否有任何方法可以确定指定字体中的精确 字形高度

我的意思是,当我想确定 DOT 字形的高度时,我应该收到较小的高度,而不是带填充的高度或字体大小。

我找到了确定精确 字形宽度的解决方案 here (我使用了第二种方法)但它不适用于高度。

更新:我需要 .NET 1.1 的解决方案

最佳答案

获取字符指标并不难。 GDI 包含一个函数 GetGlyphOutline您可以使用 GGO_METRICS 常量调用,以获取呈现时包含字形所需的最小 封闭矩形的高度和宽度。即,Arial 字体中点的 10 点字形将给出 1x1 像素的矩形,如果字体大小为 100 点,则字母 I 为 95x.14。

这些是 P/Invoke 调用的声明:

// the declarations
public struct FIXED
{
    public short fract;
    public short value;
}

public struct MAT2
{
    [MarshalAs(UnmanagedType.Struct)] public FIXED eM11;
    [MarshalAs(UnmanagedType.Struct)] public FIXED eM12;
    [MarshalAs(UnmanagedType.Struct)] public FIXED eM21;
    [MarshalAs(UnmanagedType.Struct)] public FIXED eM22;
}

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
    public int x;
    public int y;
}

[StructLayout(LayoutKind.Sequential)]
public struct POINTFX
{
    [MarshalAs(UnmanagedType.Struct)] public FIXED x;
    [MarshalAs(UnmanagedType.Struct)] public FIXED y;
}

[StructLayout(LayoutKind.Sequential)]
public struct GLYPHMETRICS
{

    public int gmBlackBoxX;
    public int gmBlackBoxY;
    [MarshalAs(UnmanagedType.Struct)] public POINT gmptGlyphOrigin;
    [MarshalAs(UnmanagedType.Struct)] public POINTFX gmptfxGlyphOrigin;
    public short gmCellIncX;
    public short gmCellIncY;

}

private const int GGO_METRICS = 0;
private const uint GDI_ERROR = 0xFFFFFFFF;

[DllImport("gdi32.dll")]
static extern uint GetGlyphOutline(IntPtr hdc, uint uChar, uint uFormat,
   out GLYPHMETRICS lpgm, uint cbBuffer, IntPtr lpvBuffer, ref MAT2 lpmat2);

[DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

如果您不考虑 P/Invoke 冗余,实际代码相当简单。我测试了代码,它有效(您也可以调整以从 GLYPHMETRICS 获取宽度)。

注意:这是临时代码,在现实世界中,您应该使用 ReleaseHandleDeleteObject 清理 HDC 和对象。感谢 user2173353 指出这一点的评论。

// if you want exact metrics, use a high font size and divide the result
// otherwise, the resulting rectangle is rounded to nearest int
private int GetGlyphHeight(char letter, string fontName, float fontPointSize)
{
    // init the font. Probably better to do this outside this function for performance
    Font font = new Font(new FontFamily(fontName), fontPointSize);
    GLYPHMETRICS metrics;

    // identity matrix, required
    MAT2 matrix = new MAT2
        {
            eM11 = {value = 1}, 
            eM12 = {value = 0}, 
            eM21 = {value = 0}, 
            eM22 = {value = 1}
        };

    // HDC needed, we use a bitmap
    using(Bitmap b = new Bitmap(1,1))
    using (Graphics g = Graphics.FromImage(b))
    {
        IntPtr hdc = g.GetHdc();
        IntPtr prev = SelectObject(hdc, font.ToHfont());
        uint retVal =  GetGlyphOutline(
             /* handle to DC   */ hdc, 
             /* the char/glyph */ letter, 
             /* format param   */ GGO_METRICS, 
             /* glyph-metrics  */ out metrics, 
             /* buffer, ignore */ 0, 
             /* buffer, ignore */ IntPtr.Zero, 
             /* trans-matrix   */ ref matrix);

        if(retVal == GDI_ERROR)
        {
            // something went wrong. Raise your own error here, 
            // or just silently ignore
            return 0;
        }


        // return the height of the smallest rectangle containing the glyph
        return metrics.gmBlackBoxY;
    }    
}

关于c# - 确定指定字体的确切字形高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9924066/

相关文章:

css - 从谷歌安装的字体看起来与通过他们的 API 获得的字体不同?

c# - 如何使用 WebServices 返回自定义对象

c# - 在静态类中使用非托管资源

winforms - .net Windows 窗体和选择 Vista 字体

c# - 嵌套的用户控件 Linkbutton Onclick 事件在回发后未触发 - asp.net/C#

fonts - Java JRE 呈现的字体与 Java JDK 不同,两者版本相同

c# - 将 int 转换为 double 时如何显示小数点及其后两位?

.net - 抛出异常时,DataAdapter.Fill()是否关闭其连接?

c# - Cosmos DB SQL API NOT IN 运算符采用 List WithParameter(List<t>) 不起作用

c# - 如何将嵌套 JSON 数据反序列化为扁平对象?