You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下筛选具备EMBED_EDITABLE权限的TrueType字体嵌入PDF的技术问询

我来帮你梳理下如何实现这个需求——枚举系统中允许编辑嵌入(EMBED_EDITABLE)的TrueType字体并填充到下拉组合框里,这在PDF嵌入场景中非常实用:

实现方案拆解

核心要做两步:先筛选出TrueType字体,再验证它的嵌入权限是否支持EMBED_EDITABLE,符合条件的才加入下拉框。

完整代码实现

1. 枚举回调函数(核心判断逻辑)

#include <windows.h>
#include <wingdi.h>

BOOL CALLBACK WFonteCombo::EnumFontProc(LPLOGFONT lplf, LPTEXTMETRIC lptm, DWORD dwType, LPARAM lpData)
{
    // 第一步:过滤非TrueType字体
    if (!(dwType & TRUETYPE_FONTTYPE))
        return TRUE; // 继续枚举下一个

    WFonteCombo* pCombo = reinterpret_cast<WFonteCombo*>(lpData);
    if (!pCombo)
        return FALSE;

    // 创建临时DC用于读取字体嵌入权限信息
    HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
    if (!hDC)
        return TRUE;

    // 选入当前枚举到的字体
    HFONT hFont = CreateFontIndirect(lplf);
    HFONT hOldFont = reinterpret_cast<HFONT>(SelectObject(hDC, hFont));

    // 读取字体OS/2表中的fsType字段(存储嵌入权限)
    DWORD embeddable = GetFontData(hDC, 0x0000, 0, NULL, 0);
    if (embeddable != GDI_ERROR)
    {
        BYTE fsType[2] = {0};
        // fsType字段在OS/2表的第38字节位置(十进制)
        if (GetFontData(hDC, 0x0000, 38, fsType, 2) == 2)
        {
            DWORD fsTypeValue = (static_cast<DWORD>(fsType[1]) << 8) | fsType[0];
            // 关键判断:EMBED_EDITABLE要求fsType的第1位(0x0002)未被设置
            // 即该位未标记时,字体允许编辑嵌入
            if (!(fsTypeValue & 0x0002))
            {
                // 将符合条件的字体名称添加到下拉框
                pCombo->AddString(lplf->lfFaceName);
            }
        }
    }

    // 清理资源,避免内存泄漏
    SelectObject(hDC, hOldFont);
    DeleteObject(hFont);
    DeleteDC(hDC);

    return TRUE; // 继续枚举剩余字体
}

2. 触发枚举的调用代码

void WFonteCombo::LoadEditableTrueTypeFonts()
{
    this->ResetContent(); // 先清空下拉框原有内容

    HDC hDC = ::GetDC(NULL);
    if (!hDC)
        return;

    LOGFONT lf = {0};
    lf.lfCharSet = DEFAULT_CHARSET; // 枚举所有字符集的字体,需特定字符集可修改此处

    // 启动字体枚举
    EnumFontFamiliesEx(hDC, &lf, (FONTENUMPROC)EnumFontProc, reinterpret_cast<LPARAM>(this), 0);

    ::ReleaseDC(NULL, hDC);
}

关键细节说明

  • 嵌入权限判断规则:TrueType字体的嵌入权限由fsType字段控制,EMBED_EDITABLE对应的是“不禁止编辑嵌入”——也就是fsType的0x0002位未被设置。如果该位被标记,说明字体不允许编辑嵌入,无法用于PDF的可编辑嵌入场景。
  • 资源管理:枚举过程中创建的临时DC、字体对象一定要及时释放,否则会造成GDI资源泄漏。
  • 字符集筛选:如果你的应用只需要特定字符集的字体(比如中文GB2312),可以把LOGFONT的lfCharSet改成GB2312_CHARSET,缩小枚举范围。

内容的提问来源于stack exchange,提问作者Penachia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:18:03