diff options
Diffstat (limited to 'src/osd/modules/font/font_dwrite.cpp')
-rw-r--r-- | src/osd/modules/font/font_dwrite.cpp | 159 |
1 files changed, 123 insertions, 36 deletions
diff --git a/src/osd/modules/font/font_dwrite.cpp b/src/osd/modules/font/font_dwrite.cpp index cfcc952ef0d..80a8ba3a810 100644 --- a/src/osd/modules/font/font_dwrite.cpp +++ b/src/osd/modules/font/font_dwrite.cpp @@ -14,7 +14,6 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> -#include <tchar.h> #include <memory> @@ -25,7 +24,6 @@ #include <initguid.h> // Direct2D -#include <dxgi1_2.h> #include <d2d1_1.h> #include <dwrite_1.h> @@ -36,11 +34,8 @@ DEFINE_GUID(GUID_WICPixelFormat8bppAlpha, 0xe6cd0116, 0xeeba, 0x4161, 0xaa, 0x85 #include <wrl\client.h> #undef interface -#include "emu.h" #include "strconv.h" #include "corestr.h" -#include "corealloc.h" -#include "fileio.h" #include "winutil.h" using namespace Microsoft::WRL; @@ -72,6 +67,16 @@ static const float POINTS_PER_DIP = (3.0f / 4.0f); #define HR_RET0( CALL ) HR_RET(CALL, 0) #define HR_RET1( CALL ) HR_RET(CALL, 1) +struct osd_deleter +{ + void operator () (void * osd_pointer) const + { + osd_free(osd_pointer); + } +}; + +typedef std::unique_ptr<char, osd_deleter> osd_utf8_ptr; + // Typedefs for dynamically loaded functions typedef lazy_loaded_function_p4<HRESULT, D2D1_FACTORY_TYPE, REFIID, const D2D1_FACTORY_OPTIONS*, void**> d2d_create_factory_fn; typedef lazy_loaded_function_p3<HRESULT, DWRITE_FACTORY_TYPE, REFIID, IUnknown**> dwrite_create_factory_fn; @@ -201,32 +206,32 @@ public: m_designUnits = designUnits; } - UINT16 DesignUnitsPerEm() + UINT16 DesignUnitsPerEm() const { return m_designUnitsPerEm; } - float EmSizeInDip() + float EmSizeInDip() const { return m_emSizeInDip; } - float DesignUnits() + float DesignUnits() const { return m_designUnits; } - int Dips() + int Dips() const { - return (int)floor((m_designUnits * m_emSizeInDip) / m_designUnitsPerEm); + return static_cast<int>(floor((m_designUnits * m_emSizeInDip) / m_designUnitsPerEm)); } - float Points() + float Points() const { return Dips() * POINTS_PER_DIP; } - FontDimension operator-(const FontDimension &other) + FontDimension operator-(const FontDimension &other) const { if (m_designUnitsPerEm != other.m_designUnitsPerEm || m_emSizeInDip != other.m_emSizeInDip) { @@ -236,7 +241,7 @@ public: return FontDimension(m_designUnitsPerEm, m_emSizeInDip, m_designUnits - other.m_designUnits); } - FontDimension operator+(const FontDimension &other) + FontDimension operator+(const FontDimension &other) const { if (m_designUnitsPerEm != other.m_designUnitsPerEm || m_emSizeInDip != other.m_emSizeInDip) { @@ -267,12 +272,12 @@ public: { } - FontDimension advanceWidth() { return m_advanceWidth; } - FontDimension abcA() { return m_a; } + FontDimension advanceWidth() const { return m_advanceWidth; } + FontDimension abcA() const { return m_a; } // Relationship between advanceWidth and B is ADV = A + B + C so B = ADV - A - C - FontDimension abcB() { return advanceWidth() - abcA() - abcC(); } - FontDimension abcC() { return m_c; } + FontDimension abcB() const { return advanceWidth() - abcA() - abcC(); } + FontDimension abcC() const { return m_c; } }; //------------------------------------------------- @@ -287,7 +292,7 @@ private: float m_emSizeInDip; public: - float EmSizeInDip() + float EmSizeInDip() const { return m_emSizeInDip; } @@ -298,25 +303,25 @@ public: m_emSizeInDip = emSizeInDip; } - FontDimension FromDip(float dip) + FontDimension FromDip(float dip) const { float sizeInDesignUnits = (dip / m_emSizeInDip) * m_designUnitsPerEm; return FontDimension(m_designUnitsPerEm, m_emSizeInDip, sizeInDesignUnits); } - FontDimension FromDesignUnit(float designUnits) + FontDimension FromDesignUnit(float designUnits) const { return FontDimension(m_designUnitsPerEm, m_emSizeInDip, designUnits); } - FontDimension FromPoint(float pointSize) + FontDimension FromPoint(float pointSize) const { float sizeInDip = pointSize * (4.0f / 3.0f); float sizeInDesignUnits = (sizeInDip / m_emSizeInDip) * m_designUnitsPerEm; return FontDimension(m_designUnitsPerEm, m_emSizeInDip, sizeInDesignUnits); } - FontABCWidths CreateAbcWidths(float advanceWidth, float leftSideBearing, float rightSideBearing) + FontABCWidths CreateAbcWidths(float advanceWidth, float leftSideBearing, float rightSideBearing) const { return FontABCWidths( FromDesignUnit(advanceWidth), @@ -341,11 +346,11 @@ private: public: osd_font_dwrite(ComPtr<ID2D1Factory> d2dfactory, ComPtr<IDWriteFactory> dwriteFactory, ComPtr<IWICImagingFactory> wicFactory) - : m_d2dfactory(d2dfactory), m_dwriteFactory(dwriteFactory), m_wicFactory(wicFactory) + : m_d2dfactory(d2dfactory), m_dwriteFactory(dwriteFactory), m_wicFactory(wicFactory), m_fontEmHeightInDips(0) { } - virtual bool open(const char *font_path, const char *_name, int &height) override + virtual bool open(std::string const &font_path, std::string const &_name, int &height) override { if (m_d2dfactory == nullptr || m_dwriteFactory == nullptr || m_wicFactory == nullptr) return false; @@ -359,11 +364,11 @@ public: bool italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0); // convert the face name - auto familyName = std::wstring(std::unique_ptr<WCHAR, void(*)(void *)>(wstring_from_utf8(name.c_str()), osd_free).get()); + std::unique_ptr<WCHAR, void(*)(void *)> familyName(wstring_from_utf8(name.c_str()), osd_free); // find the font HR_RET0(find_font( - familyName.c_str(), + familyName.get(), bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, @@ -373,7 +378,7 @@ public: m_font->GetMetrics(&metrics); m_fontEmHeightInDips = DEFAULT_EM_HEIGHT; - height = (int)round(m_fontEmHeightInDips * DIPS_PER_POINT); + height = static_cast<int>(round(m_fontEmHeightInDips * DIPS_PER_POINT)); return true; } @@ -397,7 +402,7 @@ public: // pixel of a black & white font //------------------------------------------------- - virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) override + virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs) override { const int MEM_ALIGN_CONST = 31; const int BITMAP_PAD = 50; @@ -493,7 +498,7 @@ public: target->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f)); // now draw the character - DWRITE_GLYPH_RUN run = { 0 }; + DWRITE_GLYPH_RUN run = { nullptr }; DWRITE_GLYPH_OFFSET offsets; offsets.advanceOffset = 0; offsets.ascenderOffset = 0; @@ -528,7 +533,7 @@ public: // Lock the bitmap and get the data pointer WICRect rect = { 0, 0, bmwidth, bmheight }; HR_RET0(wicBitmap->Lock(&rect, WICBitmapLockRead, lock.GetAddressOf())); - HR_RET0(lock->GetDataPointer(&cbData, (BYTE**)&pixels)); + HR_RET0(lock->GetDataPointer(&cbData, static_cast<BYTE**>(&pixels))); // determine the actual left of the character for (actbounds.min_x = 0; actbounds.min_x < bmwidth; actbounds.min_x++) @@ -610,9 +615,9 @@ private: // find_font - finds a font, given attributes //------------------------------------------------- - HRESULT find_font(std::wstring familyName, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont ** ppfont) + HRESULT find_font(std::wstring familyName, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont ** ppfont) const { - HRESULT result = S_OK; + HRESULT result; ComPtr<IDWriteFontCollection> fonts; HR_RETHR(m_dwriteFactory->GetSystemFontCollection(fonts.GetAddressOf())); @@ -695,7 +700,7 @@ public: reinterpret_cast<void**>(this->m_d2dfactory.GetAddressOf()))); // Initialize COM - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); // Create a DirectWrite factory. HR_RET1(m_pfnDWriteCreateFactory( @@ -708,15 +713,97 @@ public: NULL, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), - (void**)&m_wicFactory)); + static_cast<void**>(&m_wicFactory))); osd_printf_verbose("FontProvider: DirectWrite initialized successfully.\n"); return 0; } - virtual osd_font *font_alloc() override + virtual osd_font::ptr font_alloc() override + { + return std::make_unique<osd_font_dwrite>(m_d2dfactory, m_dwriteFactory, m_wicFactory); + } + + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &fontresult) override + { + HRESULT result; + ComPtr<IDWriteFontFamily> family; + ComPtr<IDWriteLocalizedStrings> names; + + // For now, we're just enumerating system fonts, if we want to support custom font + // collections, there's more work that neeeds to be done + ComPtr<IDWriteFontCollection> fonts; + HR_RET0(m_dwriteFactory->GetSystemFontCollection(fonts.GetAddressOf())); + + int family_count = fonts->GetFontFamilyCount(); + for (int i = 0; i < family_count; i++) + { + HR_RET0(fonts->GetFontFamily(i, family.ReleaseAndGetAddressOf())); + + HR_RET0(family->GetFamilyNames(names.ReleaseAndGetAddressOf())); + + std::unique_ptr<WCHAR[]> name = nullptr; + HR_RET0(get_localized_familyname(names, name)); + + auto utf8_name = osd_utf8_ptr(utf8_from_wstring(name.get())); + name.reset(); + + // Review: should the config name, be unlocalized? + // maybe the english name? + fontresult.push_back( + make_pair( + std::string(utf8_name.get()), + std::string(utf8_name.get()))); + + utf8_name.reset(); + } + + std::stable_sort(fontresult.begin(), fontresult.end()); + return true; + } + +private: + HRESULT get_family_for_locale(ComPtr<IDWriteLocalizedStrings> family_names, const WCHAR* locale, std::unique_ptr<WCHAR[]> &family_name) const + { + HRESULT result; + UINT32 index; + BOOL exists = false; + + result = family_names->FindLocaleName(locale, &index, &exists); + + // if the above find did not find a match, retry with US English + if (SUCCEEDED(result) && !exists) + family_names->FindLocaleName(L"en-us", &index, &exists); + + // If the specified locale doesn't exist, select the first on the list. + if (!exists) + index = 0; + + // Get the length and allocate our buffer + UINT32 name_length = 0; + HR_RETHR(family_names->GetStringLength(index, &name_length)); + auto name_buffer = std::make_unique<WCHAR[]>(name_length + 1); + + // Get the name + HR_RETHR(family_names->GetString(index, name_buffer.get(), name_length + 1)); + + family_name = std::move(name_buffer); + return S_OK; + } + + HRESULT get_localized_familyname(ComPtr<IDWriteLocalizedStrings> family_names, std::unique_ptr<WCHAR[]> &family_name) const { - return global_alloc(osd_font_dwrite(m_d2dfactory, m_dwriteFactory, m_wicFactory)); + wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; + + // Get the default locale for this user. + int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH); + + // If the default locale is returned, find that locale name, otherwise use "en-us". + if (defaultLocaleSuccess) + return get_family_for_locale(family_names, localeName, family_name); + + // If locale can't be determined, fall back to US English + return get_family_for_locale(family_names, L"en-us", family_name); } }; |