如何在MFC应用中获取TrueType字体信息以填充PDF Flags?
刚好之前做过MFC里嵌入字体到PDF的活儿,给你梳理下怎么用手里的OUTLINETEXTMETRIC结构体判断字体类型,进而填充PDF的Flags:
核心判断逻辑:从OUTLINETEXTMETRIC提取字体属性
我们主要依赖结构体里的两个字段:otmfsType(字体类型标志)和otmPanoseNumber(Panose分类数组,这个是更精准的字体风格分类)。
1. 判断衬线体(Serif)
衬线体的核心特征是字母边缘有装饰性的小线条,判断逻辑:
- 先看Panose数组的第一个元素
panbFamilyType,如果是PANOSE_FAMILY_TEXT_DISPLAY(文本/显示类字体); - 再看第二个元素
panbSerifStyle,只要它不是PANOSE_SERIF_STYLE_NONE,就属于衬线体。
比如Times New Roman的Panose里,panbSerifStyle是PANOSE_SERIF_STYLE_TRADITIONAL,明显是衬线体。
2. 判断符号体(Symbolic)
符号字体比如Wingdings、Symbol这类,本身不包含常规字母,判断起来很直接:
- 检查
otmfsType里的TMPF_SYMBOL标志:(otm.otmfsType & TMPF_SYMBOL) != 0,如果为真就是符号体; - 也可以用Panose的
panbFamilyType,如果是PANOSE_FAMILY_SYMBOL,也能确认是符号字体。
3. 判断手写体(Script)
手写体比如Brush Script MT这类,判断逻辑:
- 优先看Panose的
panbFamilyType,如果是PANOSE_FAMILY_SCRIPT,直接判定为手写体; - 要是Panose信息不全,可以 fallback 到
otmfsType的TMPF_SCRIPT标志:(otm.otmfsType & TMPF_SCRIPT) != 0,这个标志专门标记脚本/手写类字体。
对应PDF Flags的填充
PDF的字体Flags是一个32位整数,关键位的对应关系:
- 符号体(Symbolic):设置Bit 1(十六进制
0x0002) - 衬线体(Serif):设置Bit 2(十六进制
0x0004) - 手写体(Script):设置Bit 6(十六进制
0x0040) - 额外补充:如果是无衬线体(Sans-serif),可以设置Bit 3(
0x0008),对应Panose里panbSerifStyle == PANOSE_SERIF_STYLE_NONE的情况。
示例代码片段(MFC中)
假设你已经通过GetOutlineTextMetrics获取到了OUTLINETEXTMETRIC结构体实例otm:
// 初始化PDF Flags为0 DWORD pdfFontFlags = 0; // 判断符号体 if ((otm.otmfsType & TMPF_SYMBOL) != 0) { pdfFontFlags |= 0x0002; // 设置Bit 1 } // 提取Panose信息 PANOSE panose = otm.otmPanoseNumber; // 判断衬线体 if (panose.panbFamilyType == PANOSE_FAMILY_TEXT_DISPLAY && panose.panbSerifStyle != PANOSE_SERIF_STYLE_NONE) { pdfFontFlags |= 0x0004; // 设置Bit 2 } else if (panose.panbSerifStyle == PANOSE_SERIF_STYLE_NONE) { pdfFontFlags |= 0x0008; // 无衬线体,设置Bit 3 } // 判断手写体 if (panose.panbFamilyType == PANOSE_FAMILY_SCRIPT || (otm.otmfsType & TMPF_SCRIPT) != 0) { pdfFontFlags |= 0x0040; // 设置Bit 6 }
注意事项
- 部分老字体可能没有完整的Panose信息,这时候
otmfsType的标志就是可靠的 fallback; - PDF的Flags位是从Bit 1开始计数的(不是0索引),别搞混了位的对应关系;
- 如果遇到一些边缘字体(比如混合风格),可以优先以Panose的分类为准,它的颗粒度更细。
内容的提问来源于stack exchange,提问作者Penachia
相关产品推荐
相关产品推荐

