与系统相比,如何更喜欢由AddFontMemResourceEx加载的字体?

时间:2019-05-04 01:39:46

标签: c++ winapi

我正在使用C ++在Windows上使用资源中包含的字体开发游戏应用程序。

我可以通过AddFontMemResourceExCreateFont加载字体。
而且,我可以在不安装任何特殊字体的环境中正确显示带有加载字体的文本。

但是,世界上存在几种版本的字体。
如果系统中已经安装了其他版本,则CreateFont将以字体名称(pszFaceName)查找字体,并且不方便使用系统字体。
无论如何,还有AddFontMemResourceEx加载的私有字体吗?

仅供参考,AddFontMemResourceEx的返回值为HANDLE,但是我找不到任何将其用于CreateFont的代码。
可能,在专用字体上编辑字体系列可以避免冲突。 但是,如果可以的话,我想通过编程来解决。

HANDLE handle = AddFontMemResourceEx(data, readBytes, NULL, &fontNum);

hFont = CreateFont(24, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS,
                   CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"UmePlus CL Gothic");

1 个答案:

答案 0 :(得分:0)

感谢您的评论!
我已经根据注释替换了内存中的字体名称。

但是,此代码由于字节序的不同而有些复杂。

警告:newFontName必须短于oldFontName

#pragma pack(1)
typedef struct {
    short version;
    long numTables;
    short searchRange;
    short entrySelector;
    short rangeShift;
} TTF_HEADER;

typedef struct {
    char name[4];
    long checksum;
    long offset;
    long length;
} TTF_OFFSET_TABLE;

typedef struct {
    short format;
    short count;
    short stringOffset;
} TTF_NAME_TABLE_HEADER;

typedef struct {
    short platformId;
    short specificId;
    short languageId;
    short nameId;
    short length;
    short offset;
} TTF_NAME_TABLE_ENTRY;
#pragma pack()

void copySwappedWchar(const wchar_t* src, wchar_t* dest, int length) {
    for (int i = 0; i < length; i++) {
        dest[i] = _byteswap_ushort(src[i]);
    }
}

void renameLocalFont(unsigned char* data, const wchar_t* oldFontName, const wchar_t* newFontName) {
    TTF_HEADER* header = (TTF_HEADER*)data;
    unsigned char* offsetTableBase = data + sizeof(TTF_HEADER);
    for (int i = 0; i < _byteswap_ulong(header->numTables); i++) {
        TTF_OFFSET_TABLE* table = (TTF_OFFSET_TABLE*)(offsetTableBase + sizeof(TTF_OFFSET_TABLE) * i);
        if (memcmp(table->name, "name", 4) != 0) continue;

        TTF_NAME_TABLE_HEADER* nameTable = (TTF_NAME_TABLE_HEADER*)(data + _byteswap_ulong(table->offset));
        unsigned char* entryBase = data + _byteswap_ulong(table->offset) + sizeof(TTF_NAME_TABLE_HEADER);
        for (int j = 0; j < _byteswap_ushort(nameTable->count); j++) {
            TTF_NAME_TABLE_ENTRY* entry = (TTF_NAME_TABLE_ENTRY*)(entryBase + sizeof(TTF_NAME_TABLE_ENTRY) * j);
            wchar_t* dest = new wchar_t[_byteswap_ushort(entry->length) + 1];
            wchar_t* src = (wchar_t*)(data + _byteswap_ulong(table->offset) + _byteswap_ushort(nameTable->stringOffset) + _byteswap_ushort(entry->offset));
            copySwappedWchar((const wchar_t*)src, dest, _byteswap_ushort(entry->length) + 1);
            if (wcscmp(dest, oldFontName) == 0) {
                copySwappedWchar(newFontName, src, wcslen(newFontName) + 1);
            }
        }
    }
}