mirror of
https://github.com/holub/mame
synced 2025-06-04 03:46:29 +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
|
||||
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" },
|
||||
{ "cheat;c", "0", OPTION_BOOLEAN, "enable cheat subsystem" },
|
||||
{ "skip_gameinfo", "0", OPTION_BOOLEAN, "skip displaying the information screen at startup" },
|
||||
{ "uifont", "default", 0, "specify a font to use" },
|
||||
|
||||
/* image device options */
|
||||
{ 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_CHEAT "cheat"
|
||||
#define OPTION_SKIP_GAMEINFO "skip_gameinfo"
|
||||
#define OPTION_UI_FONT "uifont"
|
||||
|
||||
/* image device options */
|
||||
#define OPTION_ADDED_DEVICE_OPTIONS "added_device_options"
|
||||
|
@ -79,16 +79,18 @@ inline const char *next_line(const char *ptr)
|
||||
inline render_font::glyph &render_font::get_char(unicode_char chnum)
|
||||
{
|
||||
static glyph dummy_glyph;
|
||||
|
||||
|
||||
// grab the table; if none, return the dummy character
|
||||
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)
|
||||
return dummy_glyph;
|
||||
|
||||
// if the character isn't generated yet, do it now
|
||||
glyph &gl = glyphtable[chnum % 256];
|
||||
if (gl.bitmap == NULL)
|
||||
char_expand(gl);
|
||||
char_expand(chnum, gl);
|
||||
|
||||
// return the resulting character
|
||||
return gl;
|
||||
@ -111,9 +113,26 @@ render_font::render_font(render_manager &manager, const char *filename)
|
||||
m_yoffs(0),
|
||||
m_scale(1.0f),
|
||||
m_rawdata(NULL),
|
||||
m_rawsize(0)
|
||||
m_rawsize(0),
|
||||
m_osdfont(NULL)
|
||||
{
|
||||
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
|
||||
if (filename != NULL && load_cached_bdf(filename))
|
||||
@ -154,6 +173,10 @@ render_font::~render_font()
|
||||
|
||||
// free the raw data and the size itself
|
||||
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
|
||||
//-------------------------------------------------
|
||||
|
||||
void render_font::char_expand(glyph &gl)
|
||||
void render_font::char_expand(unicode_char chnum, glyph &gl)
|
||||
{
|
||||
// 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++)
|
||||
// if we're an OSD font, query the info
|
||||
if (m_format == FF_OSD)
|
||||
{
|
||||
int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
|
||||
UINT32 *dest = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL;
|
||||
// we set bmwidth to -1 if we've previously queried and failed
|
||||
if (gl.bmwidth == -1)
|
||||
return;
|
||||
|
||||
// attempt to get the font bitmap; if we fail, set bmwidth to -1
|
||||
gl.bitmap = m_manager.machine().osd().font_get_bitmap(m_osdfont, chnum, gl.width, gl.xoffs, gl.yoffs);
|
||||
if (gl.bitmap == NULL)
|
||||
return;
|
||||
|
||||
// text format
|
||||
if (m_format == FF_TEXT)
|
||||
// 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
|
||||
for (int x = 0; x < gl.bmwidth; x += 4)
|
||||
int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight;
|
||||
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
|
||||
int bits = -1;
|
||||
while (*ptr != 13 && bits == -1)
|
||||
// loop over bytes
|
||||
for (int x = 0; x < gl.bmwidth; x += 4)
|
||||
{
|
||||
if (*ptr >= '0' && *ptr <= '9')
|
||||
bits = *ptr++ - '0';
|
||||
else if (*ptr >= 'A' && *ptr <= 'F')
|
||||
bits = *ptr++ - 'A' + 10;
|
||||
else if (*ptr >= 'a' && *ptr <= 'f')
|
||||
bits = *ptr++ - 'a' + 10;
|
||||
else
|
||||
ptr++;
|
||||
// scan for the next hex digit
|
||||
int bits = -1;
|
||||
while (*ptr != 13 && bits == -1)
|
||||
{
|
||||
if (*ptr >= '0' && *ptr <= '9')
|
||||
bits = *ptr++ - '0';
|
||||
else if (*ptr >= 'A' && *ptr <= 'F')
|
||||
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
|
||||
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);
|
||||
}
|
||||
// advance to the next line
|
||||
ptr = next_line(ptr);
|
||||
}
|
||||
|
||||
// advance to the next line
|
||||
ptr = next_line(ptr);
|
||||
}
|
||||
|
||||
// cached format
|
||||
else if (m_format == FF_CACHED)
|
||||
{
|
||||
for (int x = 0; x < gl.bmwidth; x++)
|
||||
// cached format
|
||||
else if (m_format == FF_CACHED)
|
||||
{
|
||||
if (accumbit == 7)
|
||||
accum = *ptr++;
|
||||
if (dest != NULL)
|
||||
*dest++ = (accum & (1 << accumbit)) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff);
|
||||
accumbit = (accumbit - 1) & 7;
|
||||
for (int x = 0; x < gl.bmwidth; x++)
|
||||
{
|
||||
if (accumbit == 7)
|
||||
accum = *ptr++;
|
||||
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
|
||||
{
|
||||
public:
|
||||
INT32 width; /* width from this character to the next */
|
||||
INT32 xoffs, yoffs; /* X and Y offset from baseline to top,left of bitmap */
|
||||
INT32 bmwidth, bmheight; /* width and height of bitmap */
|
||||
const char * rawdata; /* pointer to the raw data for this one */
|
||||
bitmap_t * bitmap; /* pointer to the bitmap containing the raw data */
|
||||
render_texture * texture; /* pointer to a texture for rendering and sizing */
|
||||
INT32 width; // width from this character to the next
|
||||
INT32 xoffs, yoffs; // X and Y offset from baseline to top,left of bitmap
|
||||
INT32 bmwidth, bmheight; // width and height of bitmap
|
||||
const char * rawdata; // pointer to the raw data for this one
|
||||
bitmap_t * bitmap; // pointer to the bitmap containing the raw data
|
||||
render_texture * texture; // pointer to a texture for rendering and sizing
|
||||
};
|
||||
|
||||
// internal format
|
||||
@ -92,12 +92,13 @@ private:
|
||||
{
|
||||
FF_UNKNOWN,
|
||||
FF_TEXT,
|
||||
FF_CACHED
|
||||
FF_CACHED,
|
||||
FF_OSD
|
||||
};
|
||||
|
||||
// helpers
|
||||
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_bdf();
|
||||
bool load_cached(mame_file *file, UINT32 hash);
|
||||
@ -105,13 +106,14 @@ private:
|
||||
|
||||
// internal state
|
||||
render_manager & m_manager;
|
||||
format m_format; /* format of font data */
|
||||
int m_height; /* height of the font, from ascent to descent */
|
||||
int m_yoffs; /* y offset from baseline to descent */
|
||||
float m_scale; /* 1 / height precomputed */
|
||||
glyph * m_glyphs[256]; /* array of glyph subtables */
|
||||
const char * m_rawdata; /* pointer to the raw data for the font */
|
||||
UINT64 m_rawsize; /* size of the raw font data */
|
||||
format m_format; // format of font data
|
||||
int m_height; // height of the font, from ascent to descent
|
||||
int m_yoffs; // y offset from baseline to descent
|
||||
float m_scale; // 1 / height precomputed
|
||||
glyph * m_glyphs[256]; // array of glyph subtables
|
||||
const char * m_rawdata; // pointer to the raw data for the font
|
||||
UINT64 m_rawsize; // size of the raw font data
|
||||
osd_font m_osdfont; // handle to the OSD font
|
||||
|
||||
// constants
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
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.
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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 "osdcore.h"
|
||||
#include "unicode.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -53,6 +54,7 @@
|
||||
// forward references
|
||||
class input_type_desc;
|
||||
class device_t;
|
||||
typedef void *osd_font;
|
||||
|
||||
|
||||
// ======================> osd_interface
|
||||
@ -82,6 +84,11 @@ public:
|
||||
|
||||
// input overridables
|
||||
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:
|
||||
// internal state
|
||||
|
@ -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
|
||||
//============================================================
|
||||
|
@ -156,8 +156,15 @@ public:
|
||||
// input overridables
|
||||
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:
|
||||
static void osd_exit(running_machine &machine);
|
||||
|
||||
static const int DEFAULT_FONT_HEIGHT = 200;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user