Fix drawing characters outside Unicode BMP with SDL

Font selection on Linux seems to be working provided you don't choose C/J/K fonts
Selecting a C/J/K font causes MAME to give a black screen when dropping back to main menu
Since fallback fonts aren't used, this means you can't use the Chinese/Japanese localisations with SDL font provider
This commit is contained in:
Vas Crabb 2016-03-17 04:08:11 +11:00
parent 74e10d87fa
commit 6ecc87bc28

View File

@ -8,7 +8,12 @@
#include "font_module.h"
#include "modules/osdmodule.h"
#if defined(SDLMAME_UNIX) && (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_SOLARIS)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN))
#if defined(SDLMAME_UNIX) && !defined(SDLMAME_MACOSX) && !defined(SDLMAME_SOLARIS) && !defined(SDLMAME_HAIKU) && !defined(SDLMAME_EMSCRIPTEN)
#include "corestr.h"
#include "corealloc.h"
#include "fileio.h"
#include "unicode.h"
#include <SDL2/SDL_ttf.h>
#ifndef SDLMAME_HAIKU
@ -16,11 +21,6 @@
#endif
#include "corestr.h"
#include "corealloc.h"
#include "fileio.h"
//-------------------------------------------------
// font_open - attempt to "open" a handle to the
// font with the given name
@ -29,8 +29,8 @@
class osd_font_sdl : public osd_font
{
public:
osd_font_sdl() : m_font(nullptr) { }
osd_font_sdl(osd_font_sdl &&obj) : m_font(obj.m_font) { obj.m_font = nullptr; }
osd_font_sdl() : m_font(nullptr, &TTF_CloseFont) { }
osd_font_sdl(osd_font_sdl &&obj) : m_font(std::move(obj.m_font)) { }
virtual ~osd_font_sdl() { close(); }
virtual bool open(std::string const &font_path, std::string const &name, int &height);
@ -45,25 +45,25 @@ public:
}
private:
typedef std::unique_ptr<TTF_Font, void (*)(TTF_Font *)> TTF_Font_ptr;
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 const &name, bool bold, bool italic, bool underline, bool &bakedstyles);
TTF_Font_ptr search_font_config(std::string const &name, bool bold, bool italic, bool underline, bool &bakedstyles);
#endif
bool BDF_Check_Magic(std::string const &name);
TTF_Font * TTF_OpenFont_Magic(std::string const &name, int fsize);
TTF_Font_ptr TTF_OpenFont_Magic(std::string const &name, int fsize);
TTF_Font *m_font;
TTF_Font_ptr m_font;
};
bool osd_font_sdl::open(std::string const &font_path, std::string const &_name, int &height)
{
TTF_Font *font = nullptr;
bool bakedstyles = false;
int style = 0;
// accept qualifiers from the name
std::string name(_name);
@ -78,7 +78,7 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name,
bool const strike = (strreplace(name, "[S]", "") + strreplace(name, "[s]", "") > 0);
// first up, try it as a filename
font = TTF_OpenFont_Magic(name, POINT_SIZE);
TTF_Font_ptr font = TTF_OpenFont_Magic(name, POINT_SIZE);
// if no success, try the font path
@ -114,6 +114,7 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name,
}
// apply styles
int style = 0;
if (!bakedstyles)
{
style |= bold ? TTF_STYLE_BOLD : 0;
@ -127,12 +128,11 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name,
if (strike)
osd_printf_warning("Ignoring strikethrough for SDL_TTF older than 2.0.10\n");
#endif // PATCHLEVEL
TTF_SetFontStyle(font, style);
TTF_SetFontStyle(font.get(), style);
height = TTF_FontLineSkip(font);
height = TTF_FontLineSkip(font.get());
close();
m_font = font;
m_font = std::move(font);
return true;
}
@ -143,9 +143,7 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name,
void osd_font_sdl::close()
{
if (m_font)
TTF_CloseFont(m_font);
m_font = nullptr;
m_font.reset();
}
//-------------------------------------------------
@ -158,16 +156,10 @@ void osd_font_sdl::close()
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 };
SDL_Color const fcol = { 0xff, 0xff, 0xff };
std::uint16_t ustr[16];
ttffont = m_font;
memset(ustr,0,sizeof(ustr));
ustr[0] = (std::uint16_t)chnum;
drawsurf = TTF_RenderUNICODE_Solid(ttffont, ustr, fcol);
ustr[utf16_from_uchar(ustr, ARRAY_LENGTH(ustr), chnum)] = 0;
std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)> const drawsurf(TTF_RenderUNICODE_Solid(m_font.get(), ustr, fcol), &SDL_FreeSurface);
// was nothing returned?
if (drawsurf)
@ -178,39 +170,35 @@ bool osd_font_sdl::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, std::in
// copy the rendered character image into it
for (int y = 0; y < bitmap.height(); y++)
{
std::uint32_t *dstrow = &bitmap.pix32(y);
std::uint8_t *srcrow = (std::uint8_t *)drawsurf->pixels;
srcrow += (y * drawsurf->pitch);
std::uint32_t *const dstrow = &bitmap.pix32(y);
std::uint8_t const *const srcrow = reinterpret_cast<std::uint8_t const *>(drawsurf->pixels) + (y * drawsurf->pitch);
for (int x = 0; x < drawsurf->w; x++)
{
dstrow[x] = srcrow[x] ? rgb_t(0xff,0xff,0xff,0xff) : rgb_t(0x00,0xff,0xff,0xff);
dstrow[x] = srcrow[x] ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(0x00, 0xff, 0xff, 0xff);
}
}
// what are these?
xoffs = yoffs = 0;
width = drawsurf->w;
SDL_FreeSurface(drawsurf);
}
return bitmap.valid();
}
TTF_Font * osd_font_sdl::TTF_OpenFont_Magic(std::string const &name, int fsize)
osd_font_sdl::TTF_Font_ptr 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)
{
unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char magic[5] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
file.read(buffer,5);
if (memcmp(buffer, magic, 5))
return nullptr;
unsigned char const magic[] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
unsigned char buffer[sizeof(magic)] = { 0xff, 0xff, 0xff, 0xff, 0xff };
if ((sizeof(magic) != file.read(buffer, sizeof(magic))) || memcmp(buffer, magic, sizeof(magic)))
return TTF_Font_ptr(nullptr, &TTF_CloseFont);
file.close();
}
return TTF_OpenFont(name.c_str(), POINT_SIZE);
return TTF_Font_ptr(TTF_OpenFont(name.c_str(), POINT_SIZE), &TTF_CloseFont);
}
bool osd_font_sdl::BDF_Check_Magic(std::string const &name)
@ -218,22 +206,18 @@ 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)
{
unsigned char buffer[9];
unsigned char magic[9] = { 'S', 'T', 'A', 'R', 'T', 'F', 'O', 'N', 'T' };
file.read(buffer, 9);
file.close();
if (!memcmp(buffer, magic, 9))
unsigned char const magic[] = { 'S', 'T', 'A', 'R', 'T', 'F', 'O', 'N', 'T' };
unsigned char buffer[sizeof(magic)];
if ((sizeof(magic) != file.read(buffer, sizeof(magic))) || memcmp(buffer, magic, sizeof(magic)))
return true;
}
return false;
}
#ifndef SDLMAME_HAIKU
TTF_Font *osd_font_sdl::search_font_config(std::string const &name, bool bold, bool italic, bool underline, bool &bakedstyles)
osd_font_sdl::TTF_Font_ptr osd_font_sdl::search_font_config(std::string const &name, bool bold, bool italic, bool underline, bool &bakedstyles)
{
TTF_Font *font = nullptr;
FcValue val;
TTF_Font_ptr font(nullptr, &TTF_CloseFont);
FcConfig *const config = FcConfigGetCurrent();
std::unique_ptr<FcPattern, void (*)(FcPattern *)> pat(FcPatternCreate(), &FcPatternDestroy);
@ -262,24 +246,18 @@ TTF_Font *osd_font_sdl::search_font_config(std::string const &name, bool bold, b
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++)
for (int i = 0; (i < fontset->nfont) && !font; i++)
{
if ((FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch) ||
(val.type != FcTypeString))
FcValue val;
if ((FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) == FcResultMatch) && (val.type != FcTypeString))
{
continue;
}
osd_printf_verbose("Matching font: %s\n", val.u.s);
osd_printf_verbose("Matching font: %s\n", val.u.s);
{
std::string match_name((const char*)val.u.s);
font = TTF_OpenFont_Magic(match_name, POINT_SIZE);
}
if (font)
{
bakedstyles = true;
break;
if (font)
bakedstyles = true;
}
}
@ -294,8 +272,8 @@ TTF_Font *osd_font_sdl::search_font_config(std::string const &name, bool bold, b
for (int i = 0; (i < fontset->nfont) && !font; i++)
{
if ((FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) == FcResultMatch) &&
(val.type == FcTypeString))
FcValue val;
if ((FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) == FcResultMatch) && (val.type == FcTypeString))
{
osd_printf_verbose("Matching unstyled font: %s\n", val.u.s);
@ -340,6 +318,7 @@ public:
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();