diff options
Diffstat (limited to 'src/osd')
-rw-r--r-- | src/osd/modules/font/font_dwrite.cpp | 17 | ||||
-rw-r--r-- | src/osd/modules/font/font_module.h | 17 | ||||
-rw-r--r-- | src/osd/modules/font/font_none.cpp | 48 | ||||
-rw-r--r-- | src/osd/modules/font/font_osx.cpp | 139 | ||||
-rw-r--r-- | src/osd/modules/font/font_sdl.cpp | 199 | ||||
-rw-r--r-- | src/osd/modules/font/font_windows.cpp | 116 | ||||
-rw-r--r-- | src/osd/modules/lib/osdobj_common.cpp | 34 | ||||
-rw-r--r-- | src/osd/modules/lib/osdobj_common.h | 14 | ||||
-rw-r--r-- | src/osd/osdepend.h | 30 | ||||
-rw-r--r-- | src/osd/strconv.h | 16 |
10 files changed, 376 insertions, 254 deletions
diff --git a/src/osd/modules/font/font_dwrite.cpp b/src/osd/modules/font/font_dwrite.cpp index cfcc952ef0d..0271aeaa249 100644 --- a/src/osd/modules/font/font_dwrite.cpp +++ b/src/osd/modules/font/font_dwrite.cpp @@ -345,7 +345,7 @@ public: { } - 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 +359,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, @@ -397,7 +397,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; @@ -714,9 +714,14 @@ public: return 0; } - virtual osd_font *font_alloc() override + virtual osd_font::ptr font_alloc() override { - return global_alloc(osd_font_dwrite(m_d2dfactory, m_dwriteFactory, m_wicFactory)); + 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> > &result) override + { + return false; } }; diff --git a/src/osd/modules/font/font_module.h b/src/osd/modules/font/font_module.h index c9c7b1f40cb..81ffaca74e5 100644 --- a/src/osd/modules/font/font_module.h +++ b/src/osd/modules/font/font_module.h @@ -5,12 +5,16 @@ * */ -#ifndef FONT_MODULE_H_ -#define FONT_MODULE_H_ +#ifndef MAME_OSD_MODULES_FONT_FONTMODULE_H +#define MAME_OSD_MODULES_FONT_FONTMODULE_H #include "osdepend.h" #include "modules/osdmodule.h" +#include <string> +#include <vector> + + //============================================================ // CONSTANTS //============================================================ @@ -21,8 +25,13 @@ class font_module { public: virtual ~font_module() { } - virtual osd_font *font_alloc() = 0; + + /** attempt to allocate a font instance */ + virtual osd_font::ptr font_alloc() = 0; + + /** attempt to list available font families */ + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) = 0; }; -#endif /* FONT_MODULE_H_ */ +#endif // MAME_OSD_MODULES_FONT_FONTMODULE_H diff --git a/src/osd/modules/font/font_none.cpp b/src/osd/modules/font/font_none.cpp index de9d01bb103..2716b52cf8e 100644 --- a/src/osd/modules/font/font_none.cpp +++ b/src/osd/modules/font/font_none.cpp @@ -8,61 +8,25 @@ #include "font_module.h" #include "modules/osdmodule.h" -//------------------------------------------------- -// font_open - attempt to "open" a handle to the -// font with the given name -//------------------------------------------------- - class osd_font_none : public osd_font { public: virtual ~osd_font_none() { } - virtual bool open(const char *font_path, const char *name, int &height) override; - virtual void close() override; - virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) override; + virtual bool open(std::string const &font_path, std::string const &name, int &height) override { return false; } + virtual void close() override { } + virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs) override { return false; } }; -bool osd_font_none::open(const char *font_path, const char *_name, int &height) -{ - return false; -} - -//------------------------------------------------- -// font_close - release resources associated with -// a given OSD font -//------------------------------------------------- - -void osd_font_none::close() -{ -} - -//------------------------------------------------- -// font_get_bitmap - allocate and populate a -// BITMAP_FORMAT_ARGB32 bitmap containing the -// pixel values rgb_t(0xff,0xff,0xff,0xff) -// or rgb_t(0x00,0xff,0xff,0xff) for each -// pixel of a black & white font -//------------------------------------------------- - -bool osd_font_none::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) -{ - return false; -} - class font_none : public osd_module, public font_module { public: - font_none() : osd_module(OSD_FONT_PROVIDER, "none"), font_module() - { - } + font_none() : osd_module(OSD_FONT_PROVIDER, "none"), font_module() { } virtual int init(const osd_options &options) override { return 0; } - virtual osd_font *font_alloc() override - { - return global_alloc(osd_font_none); - } + virtual osd_font::ptr font_alloc() override { return std::make_unique<osd_font_none>(); } + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override { return false; } }; MODULE_DEFINITION(FONT_NONE, font_none) diff --git a/src/osd/modules/font/font_osx.cpp b/src/osd/modules/font/font_osx.cpp index 831321fdf34..8e310714649 100644 --- a/src/osd/modules/font/font_osx.cpp +++ b/src/osd/modules/font/font_osx.cpp @@ -10,14 +10,11 @@ #ifdef SDLMAME_MACOSX -#include <Carbon/Carbon.h> - #include "corealloc.h" #include "fileio.h" -#define POINT_SIZE 144.0 -#define EXTRA_HEIGHT 1.0 -#define EXTRA_WIDTH 1.15 +#include <ApplicationServices/ApplicationServices.h> +#include <CoreFoundation/CoreFoundation.h> //------------------------------------------------- // font_open - attempt to "open" a handle to the @@ -27,48 +24,64 @@ class osd_font_osx : public osd_font { public: - virtual ~osd_font_osx() { } + osd_font_osx() : m_font(NULL) { } + osd_font_osx(osd_font_osx &&obj) : m_font(obj.m_font) { obj.m_font = NULL; } + virtual ~osd_font_osx() { close(); } - virtual bool open(const char *font_path, const char *name, int &height); + virtual bool open(std::string const &font_path, std::string const &name, int &height); virtual void close(); - virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs); + virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs); + + osd_font_osx &operator=(osd_font_osx &&obj) + { + using std::swap; + swap(m_font, obj.m_font); + return *this; + } + private: + osd_font_osx(osd_font_osx const &) = delete; + osd_font_osx &operator=(osd_font_osx const &) = delete; + + static constexpr CGFloat POINT_SIZE = 144.0; + static constexpr CGFloat EXTRA_HEIGHT = 1.0; + static constexpr CGFloat EXTRA_WIDTH = 1.15; + CTFontRef m_font; }; -bool osd_font_osx::open(const char *font_path, const char *name, int &height) +bool osd_font_osx::open(std::string const &font_path, std::string const &name, int &height) { - m_font = NULL; - osd_printf_verbose("FONT NAME %s\n", name); + osd_printf_verbose("FONT NAME %s\n", name.c_str()); #if 0 - if (!strcmp(name, "default")) + if (name != "default") { name = "LucidaGrande"; } #endif - CFStringRef const font_name = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8); - if (kCFNotFound != CFStringFind(font_name, CFSTR(".BDF"), kCFCompareCaseInsensitive | kCFCompareBackwards | kCFCompareAnchored | kCFCompareNonliteral).location) + CFStringRef const font_name = CFStringCreateWithCString(NULL, name.c_str(), kCFStringEncodingUTF8); + if (font_name && (kCFNotFound != CFStringFind(font_name, CFSTR(".BDF"), kCFCompareCaseInsensitive | kCFCompareBackwards | kCFCompareAnchored | kCFCompareNonliteral).location)) { // handle bdf fonts in the core CFRelease(font_name); return false; } CTFontRef ct_font = NULL; - if (font_name != NULL) + if (font_name) { CTFontDescriptorRef const font_descriptor = CTFontDescriptorCreateWithNameAndSize(font_name, 0.0); - if (font_descriptor != NULL) + if (font_descriptor) { ct_font = CTFontCreateWithFontDescriptor(font_descriptor, POINT_SIZE, &CGAffineTransformIdentity); CFRelease(font_descriptor); } + CFRelease(font_name); } - CFRelease(font_name); if (!ct_font) { - osd_printf_verbose("Couldn't find/open font %s, using MAME default\n", name); + osd_printf_verbose("Couldn't find/open font %s, using MAME default\n", name.c_str()); return false; } @@ -84,6 +97,7 @@ bool osd_font_osx::open(const char *font_path, const char *name, int &height) line_height += CTFontGetLeading(ct_font); height = ceilf(line_height * EXTRA_HEIGHT); + close(); m_font = ct_font; return true; } @@ -96,9 +110,8 @@ bool osd_font_osx::open(const char *font_path, const char *name, int &height) void osd_font_osx::close() { if (m_font != NULL) - { CFRelease(m_font); - } + m_font = NULL; } //------------------------------------------------- @@ -109,7 +122,7 @@ void osd_font_osx::close() // pixel of a black & white font //------------------------------------------------- -bool osd_font_osx::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) +bool osd_font_osx::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs) { UniChar uni_char; CGGlyph glyph; @@ -180,21 +193,89 @@ bool osd_font_osx::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 & class font_osx : public osd_module, public font_module { public: - font_osx() - : osd_module(OSD_FONT_PROVIDER, "osx"), font_module() + font_osx() : osd_module(OSD_FONT_PROVIDER, "osx"), font_module() { } + + virtual int init(const osd_options &options) override { return 0; } + virtual osd_font::ptr font_alloc() override { return std::make_unique<osd_font_osx>(); } + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override; + +private: + static CFComparisonResult sort_callback(CTFontDescriptorRef first, CTFontDescriptorRef second, void *refCon) { + CFStringRef left = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(first, kCTFontDisplayNameAttribute, NULL); + if (!left) left = (CFStringRef)CTFontDescriptorCopyAttribute(first, kCTFontNameAttribute); + CFStringRef right = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(second, kCTFontDisplayNameAttribute, NULL); + if (!right) right = (CFStringRef)CTFontDescriptorCopyAttribute(second, kCTFontNameAttribute); + + CFComparisonResult result; + if (left && right) result = CFStringCompareWithOptions(left, right, CFRangeMake(0, CFStringGetLength(left)), kCFCompareCaseInsensitive | kCFCompareLocalized | kCFCompareNonliteral); + else if (!left) result = kCFCompareLessThan; + else if (!right) result = kCFCompareGreaterThan; + else result = kCFCompareEqualTo; + + if (left) CFRelease(left); + if (right) CFRelease(right); + return result; } +}; - virtual int init(const osd_options &options) { return 0; } - - osd_font *font_alloc() +bool font_osx::get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) +{ + CFStringRef keys[] = { kCTFontCollectionRemoveDuplicatesOption }; + std::uintptr_t values[ARRAY_LENGTH(keys)] = { 1 }; + CFDictionaryRef const options = CFDictionaryCreate(kCFAllocatorDefault, (void const **)keys, (void const **)values, ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, NULL); + CTFontCollectionRef const collection = CTFontCollectionCreateFromAvailableFonts(NULL); + CFRelease(options); + if (!collection) return false; + + CFArrayRef const descriptors = CTFontCollectionCreateMatchingFontDescriptorsSortedWithCallback(collection, &sort_callback, nullptr); + CFRelease(collection); + if (!descriptors) return false; + + result.clear(); + CFIndex const count = CFArrayGetCount(descriptors); + result.reserve(count); + for (CFIndex i = 0; i != count; i++) { - return global_alloc(osd_font_osx); + CTFontDescriptorRef const font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descriptors, i); + CFStringRef const name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontNameAttribute); + CFStringRef const display = (CFStringRef)CTFontDescriptorCopyLocalizedAttribute(font, kCTFontDisplayNameAttribute, NULL); + + if (name && display) + { + char const *utf; + std::vector<char> buf; + + utf = CFStringGetCStringPtr(name, kCFStringEncodingUTF8); + if (!utf) + { + buf.resize(CFStringGetMaximumSizeForEncoding(std::max(CFStringGetLength(name), CFStringGetLength(display)), kCFStringEncodingUTF8)); + CFStringGetCString(name, &buf[0], buf.size(), kCFStringEncodingUTF8); + } + std::string utf8name(utf ? utf : &buf[0]); + + utf = CFStringGetCStringPtr(display, kCFStringEncodingUTF8); + if (!utf) + { + buf.resize(CFStringGetMaximumSizeForEncoding(CFStringGetLength(display), kCFStringEncodingUTF8)); + CFStringGetCString(display, &buf[0], buf.size(), kCFStringEncodingUTF8); + } + std::string utf8display(utf ? utf : &buf[0]); + + result.emplace_back(std::move(utf8name), std::move(utf8display)); + } + + if (name) CFRelease(name); + if (display) CFRelease(display); } -}; + return true; +} + #else /* SDLMAME_MACOSX */ - MODULE_NOT_SUPPORTED(font_osx, OSD_FONT_PROVIDER, "osx") + +MODULE_NOT_SUPPORTED(font_osx, OSD_FONT_PROVIDER, "osx") + #endif MODULE_DEFINITION(FONT_OSX, font_osx) diff --git a/src/osd/modules/font/font_sdl.cpp b/src/osd/modules/font/font_sdl.cpp index ace9963a28b..bbb3f7ba049 100644 --- a/src/osd/modules/font/font_sdl.cpp +++ b/src/osd/modules/font/font_sdl.cpp @@ -20,7 +20,6 @@ #include "corealloc.h" #include "fileio.h" -#define POINT_SIZE 144.0 //------------------------------------------------- // font_open - attempt to "open" a handle to the @@ -30,38 +29,53 @@ class osd_font_sdl : public osd_font { public: - virtual ~osd_font_sdl() { } + osd_font_sdl() : m_font(nullptr) { } + osd_font_sdl(osd_font_sdl &&obj) : m_font(obj.m_font) { obj.m_font = nullptr; } + virtual ~osd_font_sdl() { close(); } - virtual bool open(const char *font_path, const char *name, int &height); + virtual bool open(std::string const &font_path, std::string const &name, int &height); virtual void close(); - virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs); + virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs); + + osd_font_sdl & operator=(osd_font_sdl &&obj) + { + using std::swap; + swap(m_font, obj.m_font); + return *this; + } + private: + osd_font_sdl(osd_font_sdl const &) = delete; + osd_font_sdl & operator=(osd_font_sdl const &) = delete; + + static constexpr double POINT_SIZE = 144.0; + #ifndef SDLMAME_HAIKU - TTF_Font *search_font_config(std::string name, bool bold, bool italic, bool underline, bool &bakedstyles); + TTF_Font *search_font_config(std::string const &name, bool bold, bool italic, bool underline, bool &bakedstyles); #endif - bool BDF_Check_Magic(std::string name); - TTF_Font * TTF_OpenFont_Magic(std::string name, int fsize); + bool BDF_Check_Magic(std::string const &name); + TTF_Font * TTF_OpenFont_Magic(std::string const &name, int fsize); + TTF_Font *m_font; }; -bool osd_font_sdl::open(const char *font_path, const char *_name, int &height) +bool osd_font_sdl::open(std::string const &font_path, std::string const &_name, int &height) { - TTF_Font *font = (TTF_Font *)NULL; + TTF_Font *font = nullptr; bool bakedstyles = false; int style = 0; // accept qualifiers from the name std::string name(_name); - - if (name.compare("default")==0) + if (name.compare("default") == 0) { name = "Liberation Sans"; } - bool bold = (strreplace(name, "[B]", "") + strreplace(name, "[b]", "") > 0); - bool italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0); - bool underline = (strreplace(name, "[U]", "") + strreplace(name, "[u]", "") > 0); - bool strike = (strreplace(name, "[S]", "") + strreplace(name, "[s]", "") > 0); + bool const bold = (strreplace(name, "[B]", "") + strreplace(name, "[b]", "") > 0); + bool const italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0); + bool const underline = (strreplace(name, "[U]", "") + strreplace(name, "[u]", "") > 0); + bool const strike = (strreplace(name, "[S]", "") + strreplace(name, "[s]", "") > 0); // first up, try it as a filename font = TTF_OpenFont_Magic(name, POINT_SIZE); @@ -72,7 +86,7 @@ bool osd_font_sdl::open(const char *font_path, const char *_name, int &height) { osd_printf_verbose("Searching font %s in -%s\n", name.c_str(), OPTION_FONTPATH); //emu_file file(options().font_path(), OPEN_FLAG_READ); - emu_file file(font_path, OPEN_FLAG_READ); + emu_file file(font_path.c_str(), OPEN_FLAG_READ); if (file.open(name.c_str()) == osd_file::error::NONE) { std::string full_name = file.fullpath(); @@ -96,7 +110,7 @@ bool osd_font_sdl::open(const char *font_path, const char *_name, int &height) { osd_printf_verbose("font %s is not TrueType or BDF, using MAME default\n", name.c_str()); } - return NULL; + return false; } // apply styles @@ -117,6 +131,7 @@ bool osd_font_sdl::open(const char *font_path, const char *_name, int &height) height = TTF_FontLineSkip(font); + close(); m_font = font; return true; } @@ -128,7 +143,9 @@ bool osd_font_sdl::open(const char *font_path, const char *_name, int &height) void osd_font_sdl::close() { - TTF_CloseFont(this->m_font); + if (m_font) + TTF_CloseFont(m_font); + m_font = nullptr; } //------------------------------------------------- @@ -139,17 +156,17 @@ void osd_font_sdl::close() // pixel of a black & white font //------------------------------------------------- -bool osd_font_sdl::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) +bool osd_font_sdl::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs) { TTF_Font *ttffont; SDL_Surface *drawsurf; SDL_Color fcol = { 0xff, 0xff, 0xff }; - UINT16 ustr[16]; + std::uint16_t ustr[16]; ttffont = m_font; memset(ustr,0,sizeof(ustr)); - ustr[0] = (UINT16)chnum; + ustr[0] = (std::uint16_t)chnum; drawsurf = TTF_RenderUNICODE_Solid(ttffont, ustr, fcol); // was nothing returned? @@ -161,8 +178,8 @@ bool osd_font_sdl::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 & // copy the rendered character image into it for (int y = 0; y < bitmap.height(); y++) { - UINT32 *dstrow = &bitmap.pix32(y); - UINT8 *srcrow = (UINT8 *)drawsurf->pixels; + std::uint32_t *dstrow = &bitmap.pix32(y); + std::uint8_t *srcrow = (std::uint8_t *)drawsurf->pixels; srcrow += (y * drawsurf->pitch); @@ -182,7 +199,7 @@ bool osd_font_sdl::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 & return bitmap.valid(); } -TTF_Font * osd_font_sdl::TTF_OpenFont_Magic(std::string name, int fsize) +TTF_Font * osd_font_sdl::TTF_OpenFont_Magic(std::string const &name, int fsize) { emu_file file(OPEN_FLAG_READ); if (file.open(name.c_str()) == osd_file::error::NONE) @@ -191,12 +208,12 @@ TTF_Font * osd_font_sdl::TTF_OpenFont_Magic(std::string name, int fsize) unsigned char magic[5] = { 0x00, 0x01, 0x00, 0x00, 0x00 }; file.read(buffer,5); if (memcmp(buffer, magic, 5)) - return NULL; + return nullptr; } return TTF_OpenFont(name.c_str(), POINT_SIZE); } -bool osd_font_sdl::BDF_Check_Magic(std::string name) +bool osd_font_sdl::BDF_Check_Magic(std::string const &name) { emu_file file(OPEN_FLAG_READ); if (file.open(name.c_str()) == osd_file::error::NONE) @@ -213,54 +230,42 @@ bool osd_font_sdl::BDF_Check_Magic(std::string name) } #ifndef SDLMAME_HAIKU -TTF_Font *osd_font_sdl::search_font_config(std::string name, bool bold, bool italic, bool underline, bool &bakedstyles) +TTF_Font *osd_font_sdl::search_font_config(std::string const &name, bool bold, bool italic, bool underline, bool &bakedstyles) { - TTF_Font *font = (TTF_Font *)NULL; - FcConfig *config; - FcPattern *pat; - FcObjectSet *os; - FcFontSet *fontset; + TTF_Font *font = nullptr; FcValue val; - config = FcConfigGetCurrent(); - pat = FcPatternCreate(); - os = FcObjectSetCreate(); - FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.c_str()); + FcConfig *const config = FcConfigGetCurrent(); + std::unique_ptr<FcPattern, void (*)(FcPattern *)> pat(FcPatternCreate(), &FcPatternDestroy); + std::unique_ptr<FcObjectSet, void (*)(FcObjectSet *)> os(FcObjectSetCreate(), &FcObjectSetDestroy); + FcPatternAddString(pat.get(), FC_FAMILY, (const FcChar8 *)name.c_str()); // try and get a font with the requested styles baked-in if (bold) { if (italic) - { - FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold Italic"); - } + FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Bold Italic"); else - { - FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold"); - } + FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Bold"); } else if (italic) { - FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Italic"); + FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Italic"); } else { - FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular"); + FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Regular"); } - FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType"); + FcPatternAddString(pat.get(), FC_FONTFORMAT, (const FcChar8 *)"TrueType"); - FcObjectSetAdd(os, FC_FILE); - fontset = FcFontList(config, pat, os); + FcObjectSetAdd(os.get(), FC_FILE); + std::unique_ptr<FcFontSet, void (*)(FcFontSet *)> fontset(FcFontList(config, pat.get(), os.get()), &FcFontSetDestroy); for (int i = 0; i < fontset->nfont; i++) { - if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch) - { - continue; - } - - if (val.type != FcTypeString) + if ((FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch) || + (val.type != FcTypeString)) { continue; } @@ -281,43 +286,25 @@ TTF_Font *osd_font_sdl::search_font_config(std::string name, bool bold, bool ita // didn't get a font above? try again with no baked-in styles if (!font) { - FcPatternDestroy(pat); - FcFontSetDestroy(fontset); - - pat = FcPatternCreate(); - FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.c_str()); - FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular"); - FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType"); - fontset = FcFontList(config, pat, os); + pat.reset(FcPatternCreate()); + FcPatternAddString(pat.get(), FC_FAMILY, (const FcChar8 *)name.c_str()); + FcPatternAddString(pat.get(), FC_STYLE, (const FcChar8 *)"Regular"); + FcPatternAddString(pat.get(), FC_FONTFORMAT, (const FcChar8 *)"TrueType"); + fontset.reset(FcFontList(config, pat.get(), os.get())); - for (int i = 0; i < fontset->nfont; i++) + for (int i = 0; (i < fontset->nfont) && !font; i++) { - if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch) + if ((FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) == FcResultMatch) && + (val.type == FcTypeString)) { - continue; - } + osd_printf_verbose("Matching unstyled font: %s\n", val.u.s); - if (val.type != FcTypeString) - { - continue; - } - - osd_printf_verbose("Matching unstyled font: %s\n", val.u.s); - { - std::string match_name((const char*)val.u.s); + std::string const match_name((const char *)val.u.s); font = TTF_OpenFont_Magic(match_name, POINT_SIZE); } - - if (font) - { - break; - } } } - FcPatternDestroy(pat); - FcObjectSetDestroy(os); - FcFontSetDestroy(fontset); return font; } #endif @@ -330,9 +317,9 @@ public: { } - osd_font *font_alloc() + osd_font::ptr font_alloc() { - return global_alloc(osd_font_sdl); + return std::make_unique<osd_font_sdl>(); } virtual int init(const osd_options &options) @@ -349,9 +336,53 @@ public: { TTF_Quit(); } + + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override; }; + +bool font_sdl::get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) +{ + result.clear(); + + // TODO: enumerate TTF files in font path, since we can load them, too + + FcConfig *const config = FcConfigGetCurrent(); + std::unique_ptr<FcPattern, void (*)(FcPattern *)> pat(FcPatternCreate(), &FcPatternDestroy); + FcPatternAddString(pat.get(), FC_FONTFORMAT, (const FcChar8 *)"TrueType"); + + std::unique_ptr<FcObjectSet, void (*)(FcObjectSet *)> os(FcObjectSetCreate(), &FcObjectSetDestroy); + FcObjectSetAdd(os.get(), FC_FAMILY); + FcObjectSetAdd(os.get(), FC_FILE); + + std::unique_ptr<FcFontSet, void (*)(FcFontSet *)> fontset(FcFontList(config, pat.get(), os.get()), &FcFontSetDestroy); + for (int i = 0; (i < fontset->nfont); i++) + { + FcValue val; + if ((FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) == FcResultMatch) && + (val.type == FcTypeString) && + (FcPatternGet(fontset->fonts[i], FC_FAMILY, 0, &val) == FcResultMatch) && + (val.type == FcTypeString)) + { + auto const compare_fonts = [](std::pair<std::string, std::string> const &a, std::pair<std::string, std::string> const &b) -> bool + { + int const first = core_stricmp(a.first.c_str(), b.first.c_str()); + if (first < 0) return true; + else if (first > 0) return false; + else return core_stricmp(b.second.c_str(), b.second.c_str()) < 0; + }; + std::pair<std::string, std::string> font((const char *)val.u.s, (const char *)val.u.s); + auto const pos = std::lower_bound(result.begin(), result.end(), font, compare_fonts); + if ((result.end() == pos) || (pos->first != font.first)) result.emplace(pos, std::move(font)); + } + } + + return true; +} + #else /* SDLMAME_UNIX */ - MODULE_NOT_SUPPORTED(font_sdl, OSD_FONT_PROVIDER, "sdl") + +MODULE_NOT_SUPPORTED(font_sdl, OSD_FONT_PROVIDER, "sdl") + #endif MODULE_DEFINITION(FONT_SDL, font_sdl) diff --git a/src/osd/modules/font/font_windows.cpp b/src/osd/modules/font/font_windows.cpp index 6d561e5cddd..0de5231f8a0 100644 --- a/src/osd/modules/font/font_windows.cpp +++ b/src/osd/modules/font/font_windows.cpp @@ -5,49 +5,64 @@ * */ +#define WIN32_LEAN_AND_MEAN + #include "font_module.h" #include "modules/osdmodule.h" #if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <commctrl.h> -#include <mmsystem.h> -#include <tchar.h> -#include <io.h> - #include "font_module.h" #include "modules/osdmodule.h" #include "strconv.h" #include "corestr.h" #include "corealloc.h" -#include "fileio.h" -//#define POINT_SIZE 144.0 -#define DEFAULT_FONT_HEIGHT (200) +#include <cstring> + +#include <windows.h> +#include <commctrl.h> +#include <mmsystem.h> +#include <tchar.h> +#include <io.h> -//------------------------------------------------- -// font_open - attempt to "open" a handle to the -// font with the given name -//------------------------------------------------- + +namespace { class osd_font_windows : public osd_font { public: osd_font_windows(): m_font(NULL) { } - virtual ~osd_font_windows() { } + osd_font_windows(osd_font_windows &&obj) : m_font(obj.m_font) { obj.m_font = NULL; } + virtual ~osd_font_windows() {close(); } - 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; virtual void close() override; - 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; + + osd_font_windows &operator=(osd_font_windows &&obj) + { + using std::swap; + swap(m_font, obj.m_font); + return *this; + } + private: + osd_font_windows(osd_font_windows const &) = delete; + osd_font_windows &operator=(osd_font_windows const &) = delete; + + //#define POINT_SIZE 144.0 + static constexpr LONG DEFAULT_HEIGHT = 200; + HGDIOBJ m_font; }; -bool osd_font_windows::open(const char *font_path, const char *_name, int &height) +bool osd_font_windows::open(std::string const &font_path, std::string const &_name, int &height) { + // don't leak a handle if we already have a font open + close(); + // accept qualifiers from the name std::string name(_name); if (name.compare("default")==0) name = "Tahoma"; @@ -56,7 +71,7 @@ bool osd_font_windows::open(const char *font_path, const char *_name, int &heigh // build a basic LOGFONT description of what we want LOGFONT logfont; - logfont.lfHeight = DEFAULT_FONT_HEIGHT; + logfont.lfHeight = DEFAULT_HEIGHT; logfont.lfWidth = 0; logfont.lfEscapement = 0; logfont.lfOrientation = 0; @@ -85,13 +100,19 @@ bool osd_font_windows::open(const char *font_path, const char *_name, int &heigh // select it into a temp DC and get the real font name HDC dummyDC = CreateCompatibleDC(NULL); HGDIOBJ oldfont = SelectObject(dummyDC, m_font); - TCHAR realname[100]; - GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname); + std::vector<TCHAR> realname((std::max)(GetTextFace(dummyDC, 0, nullptr), 0)); + int facelen = GetTextFace(dummyDC, realname.size(), &realname[0]); SelectObject(dummyDC, oldfont); DeleteDC(dummyDC); + if (facelen <= 0) + { + DeleteObject(m_font); + m_font = NULL; + return false; + } // if it doesn't match our request, fail - char *utf = utf8_from_tstring(realname); + char *utf = utf8_from_tstring(&realname[0]); int result = core_stricmp(utf, name.c_str()); osd_free(utf); @@ -115,7 +136,7 @@ void osd_font_windows::close() // delete the font ojbect if (m_font != NULL) DeleteObject(m_font); - + m_font = NULL; } //------------------------------------------------- @@ -269,20 +290,51 @@ bool osd_font_windows::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT class font_win : public osd_module, public font_module { public: - font_win() : osd_module(OSD_FONT_PROVIDER, "win"), font_module() - { - } + font_win() : osd_module(OSD_FONT_PROVIDER, "win"), font_module() { } virtual int init(const osd_options &options) override { return 0; } - virtual osd_font *font_alloc() override + virtual osd_font::ptr font_alloc() override { return std::make_unique<osd_font_windows>(); } + + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override; + +private: + static int CALLBACK font_family_callback(LOGFONT const *lpelfe, TEXTMETRIC const *lpntme, DWORD FontType, LPARAM lParam) { - return global_alloc(osd_font_windows); + auto &result = *reinterpret_cast<std::vector<std::pair<std::string, std::string> > *>(lParam); + char *face = utf8_from_tstring(lpelfe->lfFaceName); + if ((*face != '@') && (result.empty() || (result.back().first != face))) result.emplace_back(face, face); + osd_free(face); + return TRUE; } - }; -#else /* SDLMAME_UNIX */ - MODULE_NOT_SUPPORTED(font_win, OSD_FONT_PROVIDER, "win") -#endif + + +bool font_win::get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) +{ + result.clear(); + + LOGFONT logfont; + std::memset(&logfont, 0, sizeof(logfont)); + logfont.lfCharSet = DEFAULT_CHARSET; + logfont.lfFaceName[0] = '\0'; + logfont.lfPitchAndFamily = 0; + + HDC dummyDC = CreateCompatibleDC(nullptr); + HRESULT err = EnumFontFamiliesEx(dummyDC, &logfont, &font_family_callback, reinterpret_cast<LPARAM>(&result), 0); + DeleteDC(dummyDC); + + std::stable_sort(result.begin(), result.end()); + + return !FAILED(err); +} + +} // anonymous namespace + +#else // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) + +MODULE_NOT_SUPPORTED(font_win, OSD_FONT_PROVIDER, "win") + +#endif // defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) MODULE_DEFINITION(FONT_WINDOWS, font_win) diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index 5cb7cb85da4..f85a322dc58 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -508,40 +508,6 @@ void osd_common_t::customize_input_type_list(simple_list<input_type_entry> &type //------------------------------------------------- -// font_open - attempt to "open" a handle to the -// font with the given name -//------------------------------------------------- - -osd_font *osd_common_t::font_open(const char *name, int &height) -{ - return nullptr; -} - - -//------------------------------------------------- -// font_close - release resources associated with -// a given OSD font -//------------------------------------------------- - -void osd_common_t::font_close(osd_font *font) -{ -} - - -//------------------------------------------------- -// font_get_bitmap - allocate and populate a -// BITMAP_FORMAT_ARGB32 bitmap containing the -// pixel values rgb_t(0xff,0xff,0xff,0xff) -// or rgb_t(0x00,0xff,0xff,0xff) for each -// pixel of a black & white font -//------------------------------------------------- - -bool osd_common_t::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) -{ - return false; -} - -//------------------------------------------------- // get_slider_list - allocate and populate a // list of OS-dependent slider values. //------------------------------------------------- diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h index 592391b5161..27e8d29d4a5 100644 --- a/src/osd/modules/lib/osdobj_common.h +++ b/src/osd/modules/lib/osdobj_common.h @@ -10,8 +10,8 @@ #pragma once -#ifndef __OSDOBJ_COMMON_H__ -#define __OSDOBJ_COMMON__ +#ifndef MAME_OSD_LIB_OSDOBJ_COMMON_H +#define MAME_OSD_LIB_OSDOBJ_COMMON_H #include "osdepend.h" #include "modules/osdmodule.h" @@ -182,18 +182,14 @@ public: // input overridables virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override; - // font overridables - virtual osd_font *font_open(const char *name, int &height); - virtual void font_close(osd_font *font); - virtual bool font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs); - // video overridables virtual slider_state *get_slider_list() override; // command option overrides virtual bool execute_command(const char *command) override; - virtual osd_font *font_alloc() override { return m_font_module->font_alloc(); } + virtual osd_font::ptr font_alloc() override { return m_font_module->font_alloc(); } + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override { return m_font_module->get_font_families(font_path, result); } virtual osd_midi_device *create_midi_device() override { return m_midi->create_midi_device(); } @@ -286,4 +282,4 @@ debug_module *osd_debugger_creator() return global_alloc(_DeviceClass()); } -#endif /* __OSDOBJ_COMMON_H__ */ +#endif // MAME_OSD_LIB_OSDOBJ_COMMON_H diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h index 3e5b7d91e8f..b6ab45003e1 100644 --- a/src/osd/osdepend.h +++ b/src/osd/osdepend.h @@ -10,14 +10,18 @@ #pragma once -#ifndef __OSDEPEND_H__ -#define __OSDEPEND_H__ +#ifndef MAME_OSD_OSDEPEND_H +#define MAME_OSD_OSDEPEND_H #include "emucore.h" #include "osdcore.h" #include "unicode.h" #include "cliopts.h" +#include <memory> +#include <string> +#include <vector> + // forward references class input_type_entry; // FIXME: including emu.h does not work because emu.h includes osdepend.h @@ -32,11 +36,22 @@ class input_type_entry; // FIXME: including emu.h does not work because emu. class osd_font { public: - virtual ~osd_font() {} + typedef std::unique_ptr<osd_font> ptr; + + virtual ~osd_font() { } - virtual bool open(const char *font_path, const char *name, int &height) = 0; + /** attempt to "open" a handle to the font with the given name */ + virtual bool open(std::string const &font_path, std::string const &name, int &height) = 0; + + /** release resources associated with a given OSD font */ virtual void close() = 0; - virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) = 0; + + /*! + * allocate and populate a BITMAP_FORMAT_ARGB32 bitmap containing + * the pixel values rgb_t(0xff,0xff,0xff,0xff) or + * rgb_t(0x00,0xff,0xff,0xff) for each pixel of a black & white font + */ + virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::int32_t &width, std::int32_t &xoffs, std::int32_t &yoffs) = 0; }; // ======================> osd_interface @@ -68,7 +83,8 @@ public: virtual slider_state *get_slider_list() = 0; // font interface - virtual osd_font *font_alloc() = 0; + virtual osd_font::ptr font_alloc() = 0; + virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) = 0; // command option overrides virtual bool execute_command(const char *command) = 0; @@ -80,4 +96,4 @@ protected: virtual ~osd_interface() { } }; -#endif /* __OSDEPEND_H__ */ +#endif // MAME_OSD_OSDEPEND_H diff --git a/src/osd/strconv.h b/src/osd/strconv.h index 5de23d0b89b..6d23d78fbb1 100644 --- a/src/osd/strconv.h +++ b/src/osd/strconv.h @@ -6,8 +6,8 @@ // //============================================================ -#ifndef __OSD_STRCONV__ -#define __OSD_STRCONV__ +#ifndef MAME_OSD_STRCONV_H +#define MAME_OSD_STRCONV_H #include "osdcore.h" @@ -17,12 +17,14 @@ // FUNCTION PROTOTYPES //============================================================ -#if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) +#if defined(WIN32) -#if defined(SDLMAME_WIN32) +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN -#include <windows.h> #endif + +#include <windows.h> + // the result of these functions has to be released with osd_free() CHAR *astring_from_utf8(const char *s); @@ -39,7 +41,7 @@ char *utf8_from_wstring(const WCHAR *s); #define utf8_from_tstring utf8_from_astring #endif // UNICODE -#endif //SDLMAME_WIN32 +#endif // defined(WIN32) -#endif // __OSD_STRCONV__ +#endif // MAME_OSD_STRCONV_H |