On Windows, wxFontEnumerator::GetFacenames and wxFont::GetFaceName use GDI, which truncates the face name to 31 characters. It would be nice if we could get the non-truncated face name.
We can retrieve the non-truncated name via GetOutlineTextMetricsW. I'm not sure if we should use otmpFamilyName or otmpFaceName.
For a example to how to implement it, see this PR: arch1t3cht/Aegisub#155
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
I didn't know it was even possible to have font names longer than 31 characters under Windows, but I agree that it would be nice to support them if it is.
If the only way to get such a name is from wxFontEnumerator, then it would be better to fix it at this level, perhaps we could check if strlen(lfFaceName) == 31 and use GetOutlineTextMetrics() there in this case? But I also wonder what happens if you try to use a font with longer than 31 characters names in the application, does it work even after truncating it? What happens if there is more than one font on the system with the first 31 characters being equal in all of them?
Concerning the question of which field to use, there is this comment in the sources:
// FWIW otmpFaceName contains the same thing as otmpFamilyName followed // by a possible " Italic" or " Bold" or something else suffix
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
If you need a font with over 31 characters, you can use this one: fusion-pixel-12px-monospaced-zh_hans.zip
But I also wonder what happens if you try to use a font with longer than 31 characters names in the application, does it work even after truncating it?
I'm not sure what you mean by "does it work?". But, if you try to create a select a font with 31 characters (so truncated) with CreateFontIndirectW and SelectObject, it will select the font successfully.
This sample query ``Fusion Pixel 12px Monospaced zh``#include <iostream> #include <dwrite_3.h> #include <gdiplus.h> #include <vector> #include <Windows.h> int main() { HDC dc = CreateCompatibleDC(nullptr); if (dc == nullptr) { std::cerr << "Could not CreateCompatibleDC" << std::endl; return false; } LOGFONTW lf = { 0 }; lf.lfCharSet = DEFAULT_CHARSET; wcscpy_s(lf.lfFaceName, L"Fusion Pixel 12px Monospaced zh"); lf.lfItalic = 0; lf.lfWeight = 400; lf.lfOutPrecision = OUT_TT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = ANTIALIASED_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; HFONT hfont = CreateFontIndirect(&lf); if (hfont == nullptr) { std::cerr << "Could not CreateFontIndirect" << std::endl; return false; } SelectObject(dc, hfont); UINT otm_size = GetOutlineTextMetricsW(dc, 0, nullptr); if (!otm_size) { std::cerr << "Failed to initialize the otm_size" << std::endl; return false; } OUTLINETEXTMETRICW* otm = reinterpret_cast<OUTLINETEXTMETRICW*>(malloc(otm_size)); if (!GetOutlineTextMetricsW(dc, otm_size, otm)) { std::cerr << "Failed to initialize the otm" << std::endl; return false; } LPWSTR otmpFamilyName = (LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpFamilyName); LPWSTR otmpFaceName = (LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpFaceName); LPWSTR otmpStyleName = (LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpStyleName); LPWSTR otmpFullName = (LPWSTR)((DWORD_PTR)otm + (DWORD_PTR)otm->otmpFullName); std::wcout << L"Family Name: " << otmpFamilyName << std::endl; std::wcout << L"Face Name: " << otmpFaceName << std::endl; std::wcout << L"Style Name: " << otmpStyleName << std::endl; std::wcout << L"Full Name: " << otmpFullName << std::endl; int len = GetTextFaceW(dc, 0, nullptr); if (!len) { std::cerr << "Failed to get lenght GetTextFaceW" << std::endl; return false; } LPWSTR faceName = new WCHAR[len]; // len includes null terminator if (!GetTextFaceW(dc, len, faceName)) { std::cerr << "Failed to initialize GetTextFaceW" << std::endl; return false; } std::wcout << L"Face Name, but with GetTextFaceW: " << faceName << std::endl; free(faceName); free(otm); DeleteObject(hfont); DeleteDC(dc); return 0; }
Here is the result:
Family Name: Fusion Pixel 12px Monospaced zh_hans
Face Name: Fusion Pixel 12px Monospaced zh_hans Regular
Style Name: Regular
Full Name: Fusion-Pixel-12px-Monospaced-zh_hans-Regular;2023.08.24
Face Name, but with GetTextFaceW: Fusion Pixel 12px Monospaced zh_hans
So, as you can see, it is able to query the font and add the truncated text.
then it would be better to fix it at this level, perhaps we could check if
strlen(lfFaceName) == 31and useGetOutlineTextMetrics()there in this case?
Yes, that seems ok.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
I'm not sure what you mean by "does it work?". But, if you try to create a select a font with 31 characters (so truncated) with CreateFontIndirectW and SelectObject, it will select the font successfully.
Yes, this is what I meant, thanks for confirming that this does work. I still wonder what happens if there are 2 different fonts names equal up to 32nd character.
Anyhow, if you can make the changes discussed here and make a PR with them, it would be welcome!
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.![]()