我正在使用资源中包含的字体通过 C++ 在 Windows 上开发游戏应用程序。
我可以通过 AddFontMemResourceEx
和 CreateFont
加载字体。
而且,我可以在没有安装任何特殊字体的环境中正确渲染带有加载字体的文本。
但是,世界上存在多个版本的字体。
如果系统中已经安装了其他版本,CreateFont
将根据字体名称(pszFaceName
) 查找字体,并且不方便使用系统字体。
是否有更喜欢由 AddFontMemResourceEx
加载的私有(private)字体?
仅供引用,AddFontMemResourceEx
的返回值是HANDLE
,但我找不到任何将它用于CreateFont
的代码。
可能,在私有(private)字体上编辑字体系列可以避免冲突。但是,如果可以的话,我想通过编程来解决。
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");
感谢评论!
我已经根据评论替换了内存中的字体名称。
但是,由于字节序的不同,这段代码有点复杂。
注意: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);
}
}
}
}
我是一名优秀的程序员,十分优秀!