summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/font/font_dwrite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/font/font_dwrite.cpp')
-rw-r--r--src/osd/modules/font/font_dwrite.cpp159
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);
}
};