mirror of
https://github.com/holub/mame
synced 2025-06-06 21:03:47 +03:00
Added support for OSD-generated fonts. The OSD is queried first to see
if it owns a given font (based on the name), and if it does, it is responsible for generating bitmaps on the fly as characters are requested. Added new option -uifont to specify the UI font. It can be set to a filename, in which case a BDF font will be loaded. It can also be set to a font name (assuming the OSD support is present), in which case the OSD font by that name is used. The default value is 'default' which can be used by the OSD to substitute a default font or by the OSD, which will default to ui.bdf as before. In all cases, it falls back to the built-in font by default if none of the previous options works. On Windows, the OSD will default to Tahoma as the font name. Also on Windows, font names can be specified with [b] to indicate bold or [i] to indicate italic.
This commit is contained in:
parent
1b872c9b0b
commit
59559fe282
@ -1004,3 +1004,11 @@ Core misc options
|
|||||||
|
|
||||||
Forces MAME to skip displaying the game info screen. The default is
|
Forces MAME to skip displaying the game info screen. The default is
|
||||||
OFF (-noskip_gameinfo).
|
OFF (-noskip_gameinfo).
|
||||||
|
|
||||||
|
-uifont <fontname>
|
||||||
|
|
||||||
|
Specifies the name of a BDF font file to use for the UI font. If this
|
||||||
|
font cannot be found or cannot be loaded, the system will fall back
|
||||||
|
to its built-in UI font. On some platforms 'fontname' can be a system
|
||||||
|
font name instead of a BDF font file. The default is 'default' (use
|
||||||
|
the OSD-determined default font).
|
||||||
|
@ -164,6 +164,7 @@ const options_entry mame_core_options[] =
|
|||||||
{ "bios", NULL, 0, "select the system BIOS to use" },
|
{ "bios", NULL, 0, "select the system BIOS to use" },
|
||||||
{ "cheat;c", "0", OPTION_BOOLEAN, "enable cheat subsystem" },
|
{ "cheat;c", "0", OPTION_BOOLEAN, "enable cheat subsystem" },
|
||||||
{ "skip_gameinfo", "0", OPTION_BOOLEAN, "skip displaying the information screen at startup" },
|
{ "skip_gameinfo", "0", OPTION_BOOLEAN, "skip displaying the information screen at startup" },
|
||||||
|
{ "uifont", "default", 0, "specify a font to use" },
|
||||||
|
|
||||||
/* image device options */
|
/* image device options */
|
||||||
{ OPTION_ADDED_DEVICE_OPTIONS, "0", OPTION_BOOLEAN | OPTION_INTERNAL, "image device-specific options have been added" },
|
{ OPTION_ADDED_DEVICE_OPTIONS, "0", OPTION_BOOLEAN | OPTION_INTERNAL, "image device-specific options have been added" },
|
||||||
|
@ -154,6 +154,7 @@
|
|||||||
#define OPTION_BIOS "bios"
|
#define OPTION_BIOS "bios"
|
||||||
#define OPTION_CHEAT "cheat"
|
#define OPTION_CHEAT "cheat"
|
||||||
#define OPTION_SKIP_GAMEINFO "skip_gameinfo"
|
#define OPTION_SKIP_GAMEINFO "skip_gameinfo"
|
||||||
|
#define OPTION_UI_FONT "uifont"
|
||||||
|
|
||||||
/* image device options */
|
/* image device options */
|
||||||
#define OPTION_ADDED_DEVICE_OPTIONS "added_device_options"
|
#define OPTION_ADDED_DEVICE_OPTIONS "added_device_options"
|
||||||
|
@ -82,13 +82,15 @@ inline render_font::glyph &render_font::get_char(unicode_char chnum)
|
|||||||
|
|
||||||
// grab the table; if none, return the dummy character
|
// grab the table; if none, return the dummy character
|
||||||
glyph *glyphtable = m_glyphs[chnum / 256];
|
glyph *glyphtable = m_glyphs[chnum / 256];
|
||||||
|
if (glyphtable == NULL && m_format == FF_OSD)
|
||||||
|
glyphtable = m_glyphs[chnum / 256] = auto_alloc_array_clear(&m_manager.machine(), glyph, 256);
|
||||||
if (glyphtable == NULL)
|
if (glyphtable == NULL)
|
||||||
return dummy_glyph;
|
return dummy_glyph;
|
||||||
|
|
||||||
// if the character isn't generated yet, do it now
|
// if the character isn't generated yet, do it now
|
||||||
glyph &gl = glyphtable[chnum % 256];
|
glyph &gl = glyphtable[chnum % 256];
|
||||||
if (gl.bitmap == NULL)
|
if (gl.bitmap == NULL)
|
||||||
char_expand(gl);
|
char_expand(chnum, gl);
|
||||||
|
|
||||||
// return the resulting character
|
// return the resulting character
|
||||||
return gl;
|
return gl;
|
||||||
@ -111,10 +113,27 @@ render_font::render_font(render_manager &manager, const char *filename)
|
|||||||
m_yoffs(0),
|
m_yoffs(0),
|
||||||
m_scale(1.0f),
|
m_scale(1.0f),
|
||||||
m_rawdata(NULL),
|
m_rawdata(NULL),
|
||||||
m_rawsize(0)
|
m_rawsize(0),
|
||||||
|
m_osdfont(NULL)
|
||||||
{
|
{
|
||||||
memset(m_glyphs, 0, sizeof(m_glyphs));
|
memset(m_glyphs, 0, sizeof(m_glyphs));
|
||||||
|
|
||||||
|
// if this is an OSD font, we're done
|
||||||
|
if (filename != NULL)
|
||||||
|
{
|
||||||
|
m_osdfont = manager.machine().osd().font_open(filename, m_height);
|
||||||
|
if (m_osdfont != NULL)
|
||||||
|
{
|
||||||
|
m_scale = 1.0f / (float)m_height;
|
||||||
|
m_format = FF_OSD;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the filename is 'default' default to 'ui.bdf' for backwards compatibility
|
||||||
|
if (mame_stricmp(filename, "default") == 0)
|
||||||
|
filename = "ui.bdf";
|
||||||
|
|
||||||
// attempt to load the cached version of the font first
|
// attempt to load the cached version of the font first
|
||||||
if (filename != NULL && load_cached_bdf(filename))
|
if (filename != NULL && load_cached_bdf(filename))
|
||||||
return;
|
return;
|
||||||
@ -154,6 +173,10 @@ render_font::~render_font()
|
|||||||
|
|
||||||
// free the raw data and the size itself
|
// free the raw data and the size itself
|
||||||
auto_free(&m_manager.machine(), m_rawdata);
|
auto_free(&m_manager.machine(), m_rawdata);
|
||||||
|
|
||||||
|
// release the OSD font
|
||||||
|
if (m_osdfont != NULL)
|
||||||
|
m_manager.machine().osd().font_close(m_osdfont);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -162,68 +185,89 @@ render_font::~render_font()
|
|||||||
// character into a bitmap
|
// character into a bitmap
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
void render_font::char_expand(glyph &gl)
|
void render_font::char_expand(unicode_char chnum, glyph &gl)
|
||||||
{
|
{
|
||||||
// punt if nothing there
|
// if we're an OSD font, query the info
|
||||||
if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == NULL)
|
if (m_format == FF_OSD)
|
||||||
return;
|
|
||||||
|
|
||||||
// allocate a new bitmap of the size we need
|
|
||||||
gl.bitmap = auto_alloc(&m_manager.machine(), bitmap_t(gl.bmwidth, m_height, BITMAP_FORMAT_ARGB32));
|
|
||||||
bitmap_fill(gl.bitmap, NULL, 0);
|
|
||||||
|
|
||||||
// extract the data
|
|
||||||
const char *ptr = gl.rawdata;
|
|
||||||
UINT8 accum = 0, accumbit = 7;
|
|
||||||
for (int y = 0; y < gl.bmheight; y++)
|
|
||||||
{
|
{
|
||||||
int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
|
// we set bmwidth to -1 if we've previously queried and failed
|
||||||
UINT32 *dest = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL;
|
if (gl.bmwidth == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
// text format
|
// attempt to get the font bitmap; if we fail, set bmwidth to -1
|
||||||
if (m_format == FF_TEXT)
|
gl.bitmap = m_manager.machine().osd().font_get_bitmap(m_osdfont, chnum, gl.width, gl.xoffs, gl.yoffs);
|
||||||
|
if (gl.bitmap == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// populate the bmwidth/bmheight fields
|
||||||
|
gl.bmwidth = gl.bitmap->width;
|
||||||
|
gl.bmheight = gl.bitmap->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// other formats need to parse their data
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// punt if nothing there
|
||||||
|
if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// allocate a new bitmap of the size we need
|
||||||
|
gl.bitmap = auto_alloc(&m_manager.machine(), bitmap_t(gl.bmwidth, m_height, BITMAP_FORMAT_ARGB32));
|
||||||
|
bitmap_fill(gl.bitmap, NULL, 0);
|
||||||
|
|
||||||
|
// extract the data
|
||||||
|
const char *ptr = gl.rawdata;
|
||||||
|
UINT8 accum = 0, accumbit = 7;
|
||||||
|
for (int y = 0; y < gl.bmheight; y++)
|
||||||
{
|
{
|
||||||
// loop over bytes
|
int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
|
||||||
for (int x = 0; x < gl.bmwidth; x += 4)
|
UINT32 *dest = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL;
|
||||||
|
|
||||||
|
// text format
|
||||||
|
if (m_format == FF_TEXT)
|
||||||
{
|
{
|
||||||
// scan for the next hex digit
|
// loop over bytes
|
||||||
int bits = -1;
|
for (int x = 0; x < gl.bmwidth; x += 4)
|
||||||
while (*ptr != 13 && bits == -1)
|
|
||||||
{
|
{
|
||||||
if (*ptr >= '0' && *ptr <= '9')
|
// scan for the next hex digit
|
||||||
bits = *ptr++ - '0';
|
int bits = -1;
|
||||||
else if (*ptr >= 'A' && *ptr <= 'F')
|
while (*ptr != 13 && bits == -1)
|
||||||
bits = *ptr++ - 'A' + 10;
|
{
|
||||||
else if (*ptr >= 'a' && *ptr <= 'f')
|
if (*ptr >= '0' && *ptr <= '9')
|
||||||
bits = *ptr++ - 'a' + 10;
|
bits = *ptr++ - '0';
|
||||||
else
|
else if (*ptr >= 'A' && *ptr <= 'F')
|
||||||
ptr++;
|
bits = *ptr++ - 'A' + 10;
|
||||||
|
else if (*ptr >= 'a' && *ptr <= 'f')
|
||||||
|
bits = *ptr++ - 'a' + 10;
|
||||||
|
else
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand the four bits
|
||||||
|
if (dest != NULL)
|
||||||
|
{
|
||||||
|
*dest++ = (bits & 8) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
||||||
|
*dest++ = (bits & 4) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
||||||
|
*dest++ = (bits & 2) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
||||||
|
*dest++ = (bits & 1) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand the four bits
|
// advance to the next line
|
||||||
if (dest != NULL)
|
ptr = next_line(ptr);
|
||||||
{
|
|
||||||
*dest++ = (bits & 8) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
|
||||||
*dest++ = (bits & 4) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
|
||||||
*dest++ = (bits & 2) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
|
||||||
*dest++ = (bits & 1) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// advance to the next line
|
// cached format
|
||||||
ptr = next_line(ptr);
|
else if (m_format == FF_CACHED)
|
||||||
}
|
|
||||||
|
|
||||||
// cached format
|
|
||||||
else if (m_format == FF_CACHED)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < gl.bmwidth; x++)
|
|
||||||
{
|
{
|
||||||
if (accumbit == 7)
|
for (int x = 0; x < gl.bmwidth; x++)
|
||||||
accum = *ptr++;
|
{
|
||||||
if (dest != NULL)
|
if (accumbit == 7)
|
||||||
*dest++ = (accum & (1 << accumbit)) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
accum = *ptr++;
|
||||||
accumbit = (accumbit - 1) & 7;
|
if (dest != NULL)
|
||||||
|
*dest++ = (accum & (1 << accumbit)) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
||||||
|
accumbit = (accumbit - 1) & 7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,12 +79,12 @@ private:
|
|||||||
class glyph
|
class glyph
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
INT32 width; /* width from this character to the next */
|
INT32 width; // width from this character to the next
|
||||||
INT32 xoffs, yoffs; /* X and Y offset from baseline to top,left of bitmap */
|
INT32 xoffs, yoffs; // X and Y offset from baseline to top,left of bitmap
|
||||||
INT32 bmwidth, bmheight; /* width and height of bitmap */
|
INT32 bmwidth, bmheight; // width and height of bitmap
|
||||||
const char * rawdata; /* pointer to the raw data for this one */
|
const char * rawdata; // pointer to the raw data for this one
|
||||||
bitmap_t * bitmap; /* pointer to the bitmap containing the raw data */
|
bitmap_t * bitmap; // pointer to the bitmap containing the raw data
|
||||||
render_texture * texture; /* pointer to a texture for rendering and sizing */
|
render_texture * texture; // pointer to a texture for rendering and sizing
|
||||||
};
|
};
|
||||||
|
|
||||||
// internal format
|
// internal format
|
||||||
@ -92,12 +92,13 @@ private:
|
|||||||
{
|
{
|
||||||
FF_UNKNOWN,
|
FF_UNKNOWN,
|
||||||
FF_TEXT,
|
FF_TEXT,
|
||||||
FF_CACHED
|
FF_CACHED,
|
||||||
|
FF_OSD
|
||||||
};
|
};
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
glyph &get_char(unicode_char chnum);
|
glyph &get_char(unicode_char chnum);
|
||||||
void char_expand(glyph &ch);
|
void char_expand(unicode_char chnum, glyph &ch);
|
||||||
bool load_cached_bdf(const char *filename);
|
bool load_cached_bdf(const char *filename);
|
||||||
bool load_bdf();
|
bool load_bdf();
|
||||||
bool load_cached(mame_file *file, UINT32 hash);
|
bool load_cached(mame_file *file, UINT32 hash);
|
||||||
@ -105,13 +106,14 @@ private:
|
|||||||
|
|
||||||
// internal state
|
// internal state
|
||||||
render_manager & m_manager;
|
render_manager & m_manager;
|
||||||
format m_format; /* format of font data */
|
format m_format; // format of font data
|
||||||
int m_height; /* height of the font, from ascent to descent */
|
int m_height; // height of the font, from ascent to descent
|
||||||
int m_yoffs; /* y offset from baseline to descent */
|
int m_yoffs; // y offset from baseline to descent
|
||||||
float m_scale; /* 1 / height precomputed */
|
float m_scale; // 1 / height precomputed
|
||||||
glyph * m_glyphs[256]; /* array of glyph subtables */
|
glyph * m_glyphs[256]; // array of glyph subtables
|
||||||
const char * m_rawdata; /* pointer to the raw data for the font */
|
const char * m_rawdata; // pointer to the raw data for the font
|
||||||
UINT64 m_rawsize; /* size of the raw font data */
|
UINT64 m_rawsize; // size of the raw font data
|
||||||
|
osd_font m_osdfont; // handle to the OSD font
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
static const int CACHED_CHAR_SIZE = 12;
|
static const int CACHED_CHAR_SIZE = 12;
|
||||||
|
@ -240,7 +240,7 @@ int ui_init(running_machine *machine)
|
|||||||
machine->add_notifier(MACHINE_NOTIFY_EXIT, ui_exit);
|
machine->add_notifier(MACHINE_NOTIFY_EXIT, ui_exit);
|
||||||
|
|
||||||
/* allocate the font and messagebox string */
|
/* allocate the font and messagebox string */
|
||||||
ui_font = machine->render().font_alloc("ui.bdf");
|
ui_font = machine->render().font_alloc(options_get_string(machine->options(), OPTION_UI_FONT));
|
||||||
|
|
||||||
/* initialize the other UI bits */
|
/* initialize the other UI bits */
|
||||||
ui_menu_init(machine);
|
ui_menu_init(machine);
|
||||||
|
@ -196,3 +196,38 @@ void osd_interface::customize_input_type_list(input_type_desc *typelist)
|
|||||||
// Scan the list, and change the keys/joysticks you want.
|
// Scan the list, and change the keys/joysticks you want.
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// font_open - attempt to "open" a handle to the
|
||||||
|
// font with the given name
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
osd_font osd_interface::font_open(const char *name, int &height)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// font_close - release resources associated with
|
||||||
|
// a given OSD font
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void osd_interface::font_close(osd_font font)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// font_get_bitmap - allocate and populate a
|
||||||
|
// BITMAP_FORMAT_ARGB32 bitmap containing the
|
||||||
|
// pixel values MAKE_ARGB(0xff,0xff,0xff,0xff)
|
||||||
|
// or MAKE_ARGB(0x00,0xff,0xff,0xff) for each
|
||||||
|
// pixel of a black & white font
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
bitmap_t *osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include "emucore.h"
|
#include "emucore.h"
|
||||||
#include "osdcore.h"
|
#include "osdcore.h"
|
||||||
|
#include "unicode.h"
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -53,6 +54,7 @@
|
|||||||
// forward references
|
// forward references
|
||||||
class input_type_desc;
|
class input_type_desc;
|
||||||
class device_t;
|
class device_t;
|
||||||
|
typedef void *osd_font;
|
||||||
|
|
||||||
|
|
||||||
// ======================> osd_interface
|
// ======================> osd_interface
|
||||||
@ -83,6 +85,11 @@ public:
|
|||||||
// input overridables
|
// input overridables
|
||||||
virtual void customize_input_type_list(input_type_desc *typelist);
|
virtual void customize_input_type_list(input_type_desc *typelist);
|
||||||
|
|
||||||
|
// font overridables
|
||||||
|
virtual osd_font font_open(const char *name, int &height);
|
||||||
|
virtual void font_close(osd_font font);
|
||||||
|
virtual bitmap_t *font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// internal state
|
// internal state
|
||||||
running_machine * m_machine;
|
running_machine * m_machine;
|
||||||
|
@ -659,6 +659,226 @@ void windows_osd_interface::osd_exit(running_machine &machine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// font_open - attempt to "open" a handle to the
|
||||||
|
// font with the given name
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
osd_font windows_osd_interface::font_open(const char *_name, int &height)
|
||||||
|
{
|
||||||
|
// accept qualifiers from the name
|
||||||
|
astring name(_name);
|
||||||
|
if (name == "default") name = "Tahoma";
|
||||||
|
bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
|
||||||
|
bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
|
||||||
|
|
||||||
|
// build a basic LOGFONT description of what we want
|
||||||
|
LOGFONT logfont;
|
||||||
|
logfont.lfHeight = DEFAULT_FONT_HEIGHT;
|
||||||
|
logfont.lfWidth = 0;
|
||||||
|
logfont.lfEscapement = 0;
|
||||||
|
logfont.lfOrientation = 0;
|
||||||
|
logfont.lfWeight = bold ? FW_BOLD : FW_MEDIUM;
|
||||||
|
logfont.lfItalic = italic;
|
||||||
|
logfont.lfUnderline = FALSE;
|
||||||
|
logfont.lfStrikeOut = FALSE;
|
||||||
|
logfont.lfCharSet = ANSI_CHARSET;
|
||||||
|
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||||
|
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||||
|
logfont.lfQuality = NONANTIALIASED_QUALITY;
|
||||||
|
logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||||||
|
|
||||||
|
// copy in the face name
|
||||||
|
TCHAR *face = tstring_from_utf8(name);
|
||||||
|
_tcsncpy(logfont.lfFaceName, face, sizeof(logfont.lfFaceName) / sizeof(TCHAR));
|
||||||
|
logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR) - 1] = 0;
|
||||||
|
osd_free(face);
|
||||||
|
|
||||||
|
// create the font
|
||||||
|
height = logfont.lfHeight;
|
||||||
|
osd_font font = reinterpret_cast<osd_font>(CreateFontIndirect(&logfont));
|
||||||
|
if (font == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// select it into a temp DC and get the real font name
|
||||||
|
HDC dummyDC = CreateCompatibleDC(NULL);
|
||||||
|
HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
|
||||||
|
TCHAR realname[100];
|
||||||
|
GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname);
|
||||||
|
SelectObject(dummyDC, oldfont);
|
||||||
|
DeleteDC(dummyDC);
|
||||||
|
|
||||||
|
// if it doesn't match our request, fail
|
||||||
|
char *utf = utf8_from_tstring(realname);
|
||||||
|
int result = mame_stricmp(utf, name);
|
||||||
|
osd_free(utf);
|
||||||
|
|
||||||
|
// if we didn't match, nuke our font and fall back
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
DeleteObject(reinterpret_cast<HFONT>(font));
|
||||||
|
font = NULL;
|
||||||
|
}
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// font_close - release resources associated with
|
||||||
|
// a given OSD font
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void windows_osd_interface::font_close(osd_font font)
|
||||||
|
{
|
||||||
|
// delete the font ojbect
|
||||||
|
if (font != NULL)
|
||||||
|
DeleteObject(reinterpret_cast<HFONT>(font));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// font_get_bitmap - allocate and populate a
|
||||||
|
// BITMAP_FORMAT_ARGB32 bitmap containing the
|
||||||
|
// pixel values MAKE_ARGB(0xff,0xff,0xff,0xff)
|
||||||
|
// or MAKE_ARGB(0x00,0xff,0xff,0xff) for each
|
||||||
|
// pixel of a black & white font
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
bitmap_t *windows_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs)
|
||||||
|
{
|
||||||
|
// create a dummy DC to work with
|
||||||
|
HDC dummyDC = CreateCompatibleDC(NULL);
|
||||||
|
HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
|
||||||
|
|
||||||
|
// get the text metrics
|
||||||
|
TEXTMETRIC metrics = { 0 };
|
||||||
|
GetTextMetrics(dummyDC, &metrics);
|
||||||
|
|
||||||
|
// get the width of this character
|
||||||
|
ABC abc;
|
||||||
|
if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
|
||||||
|
{
|
||||||
|
abc.abcA = 0;
|
||||||
|
abc.abcC = 0;
|
||||||
|
GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
|
||||||
|
}
|
||||||
|
width = abc.abcA + abc.abcB + abc.abcC;
|
||||||
|
|
||||||
|
// determine desired bitmap size
|
||||||
|
int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
|
||||||
|
int bmheight = 50 + metrics.tmHeight + 50;
|
||||||
|
|
||||||
|
// describe the bitmap we want
|
||||||
|
BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)] = { 0 };
|
||||||
|
BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
|
||||||
|
info.bmiHeader.biSize = sizeof(info.bmiHeader);
|
||||||
|
info.bmiHeader.biWidth = bmwidth;
|
||||||
|
info.bmiHeader.biHeight = -bmheight;
|
||||||
|
info.bmiHeader.biPlanes = 1;
|
||||||
|
info.bmiHeader.biBitCount = 1;
|
||||||
|
info.bmiHeader.biCompression = BI_RGB;
|
||||||
|
info.bmiHeader.biSizeImage = 0;
|
||||||
|
info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
|
||||||
|
info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
|
||||||
|
info.bmiHeader.biClrUsed = 0;
|
||||||
|
info.bmiHeader.biClrImportant = 0;
|
||||||
|
info.bmiColors[0].rgbBlue = info.bmiColors[0].rgbGreen = info.bmiColors[0].rgbRed = 0x00;
|
||||||
|
info.bmiColors[1].rgbBlue = info.bmiColors[1].rgbGreen = info.bmiColors[1].rgbRed = 0xff;
|
||||||
|
|
||||||
|
// create a DIB to render to
|
||||||
|
BYTE *bits;
|
||||||
|
HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);
|
||||||
|
HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);
|
||||||
|
|
||||||
|
// clear the bitmap
|
||||||
|
int rowbytes = bmwidth / 8;
|
||||||
|
memset(bits, 0, rowbytes * bmheight);
|
||||||
|
|
||||||
|
// now draw the character
|
||||||
|
WCHAR tempchar = chnum;
|
||||||
|
SetTextColor(dummyDC, RGB(0xff,0xff,0xff));
|
||||||
|
SetBkColor(dummyDC, RGB(0x00,0x00,0x00));
|
||||||
|
ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);
|
||||||
|
|
||||||
|
// characters are expected to be full-height
|
||||||
|
rectangle actbounds;
|
||||||
|
actbounds.min_y = 50;
|
||||||
|
actbounds.max_y = 50 + metrics.tmHeight - 1;
|
||||||
|
|
||||||
|
// determine the actual left of the character
|
||||||
|
for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
|
||||||
|
{
|
||||||
|
BYTE *offs = bits + actbounds.min_x;
|
||||||
|
UINT8 summary = 0;
|
||||||
|
for (int y = 0; y < bmheight; y++)
|
||||||
|
summary |= offs[y * rowbytes];
|
||||||
|
if (summary != 0)
|
||||||
|
{
|
||||||
|
actbounds.min_x *= 8;
|
||||||
|
if (!(summary & 0x80)) actbounds.min_x++;
|
||||||
|
if (!(summary & 0xc0)) actbounds.min_x++;
|
||||||
|
if (!(summary & 0xe0)) actbounds.min_x++;
|
||||||
|
if (!(summary & 0xf0)) actbounds.min_x++;
|
||||||
|
if (!(summary & 0xf8)) actbounds.min_x++;
|
||||||
|
if (!(summary & 0xfc)) actbounds.min_x++;
|
||||||
|
if (!(summary & 0xfe)) actbounds.min_x++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine the actual right of the character
|
||||||
|
for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
|
||||||
|
{
|
||||||
|
BYTE *offs = bits + actbounds.max_x;
|
||||||
|
UINT8 summary = 0;
|
||||||
|
for (int y = 0; y < bmheight; y++)
|
||||||
|
summary |= offs[y * rowbytes];
|
||||||
|
if (summary != 0)
|
||||||
|
{
|
||||||
|
actbounds.max_x *= 8;
|
||||||
|
if (summary & 0x7f) actbounds.max_x++;
|
||||||
|
if (summary & 0x3f) actbounds.max_x++;
|
||||||
|
if (summary & 0x1f) actbounds.max_x++;
|
||||||
|
if (summary & 0x0f) actbounds.max_x++;
|
||||||
|
if (summary & 0x07) actbounds.max_x++;
|
||||||
|
if (summary & 0x03) actbounds.max_x++;
|
||||||
|
if (summary & 0x01) actbounds.max_x++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate a new bitmap
|
||||||
|
bitmap_t *bitmap = NULL;
|
||||||
|
if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
|
||||||
|
{
|
||||||
|
bitmap = auto_alloc(&machine(), bitmap_t(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y, BITMAP_FORMAT_ARGB32));
|
||||||
|
|
||||||
|
// copy the bits into it
|
||||||
|
for (int y = 0; y < bitmap->height; y++)
|
||||||
|
{
|
||||||
|
UINT32 *dstrow = BITMAP_ADDR32(bitmap, y, 0);
|
||||||
|
UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
|
||||||
|
for (int x = 0; x < bitmap->width; x++)
|
||||||
|
{
|
||||||
|
int effx = x + actbounds.min_x;
|
||||||
|
dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the final offset values
|
||||||
|
xoffs = actbounds.min_x - (50 + abc.abcA);
|
||||||
|
yoffs = actbounds.max_y - (50 + metrics.tmAscent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// de-select the font and release the DC
|
||||||
|
SelectObject(dummyDC, oldbitmap);
|
||||||
|
DeleteObject(dib);
|
||||||
|
SelectObject(dummyDC, oldfont);
|
||||||
|
DeleteDC(dummyDC);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// winmain_dump_stack
|
// winmain_dump_stack
|
||||||
//============================================================
|
//============================================================
|
||||||
|
@ -156,8 +156,15 @@ public:
|
|||||||
// input overridables
|
// input overridables
|
||||||
virtual void customize_input_type_list(input_type_desc *typelist);
|
virtual void customize_input_type_list(input_type_desc *typelist);
|
||||||
|
|
||||||
|
// font overridables
|
||||||
|
virtual osd_font font_open(const char *name, int &height);
|
||||||
|
virtual void font_close(osd_font font);
|
||||||
|
virtual bitmap_t *font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void osd_exit(running_machine &machine);
|
static void osd_exit(running_machine &machine);
|
||||||
|
|
||||||
|
static const int DEFAULT_FONT_HEIGHT = 200;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user