Moved font code into osd/modules/font. Extended osd_font to a proper

interface. (nw)
This commit is contained in:
couriersud 2015-01-19 21:47:09 +01:00
parent f07d274ac7
commit a80f04072d
12 changed files with 927 additions and 957 deletions

View File

@ -89,12 +89,17 @@ render_font::render_font(render_manager &manager, const char *filename)
// if this is an OSD font, we're done
if (filename != NULL)
{
m_osdfont = manager.machine().osd().font_open(filename, m_height);
m_osdfont = manager.machine().osd().font_alloc();
if (m_osdfont != NULL)
{
m_scale = 1.0f / (float)m_height;
m_format = FF_OSD;
return;
if (m_osdfont->open(manager.machine().options().font_path(), filename, m_height))
{
m_scale = 1.0f / (float)m_height;
m_format = FF_OSD;
return;
}
global_free(m_osdfont);
m_osdfont = NULL;
}
}
@ -130,7 +135,10 @@ render_font::~render_font()
// release the OSD font
if (m_osdfont != NULL)
m_manager.machine().osd().font_close(m_osdfont);
{
m_osdfont->close();
global_free(m_osdfont);
}
}
@ -149,7 +157,7 @@ void render_font::char_expand(unicode_char chnum, glyph &gl)
return;
// attempt to get the font bitmap; if we fail, set bmwidth to -1
if (!m_manager.machine().osd().font_get_bitmap(m_osdfont, chnum, gl.bitmap, gl.width, gl.xoffs, gl.yoffs))
if (!m_osdfont->get_bitmap(chnum, gl.bitmap, gl.width, gl.xoffs, gl.yoffs))
{
gl.bitmap.reset();
gl.bmwidth = -1;

View File

@ -0,0 +1,58 @@
/*
* font_sdl.c
*
*/
#include "osdepend.h"
#include "astring.h"
#include "corealloc.h"
#include "fileio.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);
virtual void close();
virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
private:
};
osd_font *osd_font_alloc()
{
return global_alloc(osd_font_none);
}
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;
}

View File

@ -0,0 +1,185 @@
/*
* font_sdl.c
*
*/
#include <Carbon/Carbon.h>
#include "osdepend.h"
#include "astring.h"
#include "corealloc.h"
#include "fileio.h"
#define POINT_SIZE 144.0
#define EXTRA_HEIGHT 1.0
#define EXTRA_WIDTH 1.15
//-------------------------------------------------
// font_open - attempt to "open" a handle to the
// font with the given name
//-------------------------------------------------
class osd_font_osx : public osd_font
{
public:
virtual ~osd_font_osx() {};
virtual bool open(const char *font_path, const char *name, int &height);
virtual void close();
virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
private:
CTFontRef m_font;
};
osd_font *osd_font_alloc()
{
return global_alloc(osd_font_osx);
}
bool osd_font_osx::open(const char *font_path, const char *_name, int &height)
{
CFStringRef font_name = NULL;
CTFontRef ct_font = NULL;
CTFontDescriptorRef font_descriptor;
CGAffineTransform affine_transform = CGAffineTransformIdentity;
m_font = NULL;
astring name(_name);
printf("FONT NAME %s\n", _name);
#if 0
if (name == "default")
{
name = "LucidaGrande";
}
#endif
/* handle bdf fonts in the core */
if (name.len() > 4)
if (name.makeupper().substr(name.len()-4,4) == ".BDF" )
return false;
font_name = CFStringCreateWithCString( NULL, name.cstr(), kCFStringEncodingUTF8 );
if( font_name != NULL )
{
font_descriptor = CTFontDescriptorCreateWithNameAndSize( font_name, 0.0); //POINT_SIZE );
if( font_descriptor != NULL )
{
ct_font = CTFontCreateWithFontDescriptor( font_descriptor, POINT_SIZE, &affine_transform );
CFRelease( font_descriptor );
}
}
CFRelease( font_name );
if (!ct_font)
{
osd_printf_verbose("Couldn't find/open font %s, using MAME default\n", name.cstr());
return false;
}
CFStringRef real_name = CTFontCopyPostScriptName( ct_font );
char real_name_c_string[255];
CFStringGetCString ( real_name, real_name_c_string, 255, kCFStringEncodingUTF8 );
osd_printf_verbose("Matching font: %s\n", real_name_c_string);
CFRelease( real_name );
CGFloat line_height = 0.0;
line_height += CTFontGetAscent(ct_font);
line_height += CTFontGetDescent(ct_font);
line_height += CTFontGetLeading(ct_font);
height = ceilf(line_height * EXTRA_HEIGHT);
m_font = ct_font;
return true;
}
//-------------------------------------------------
// font_close - release resources associated with
// a given OSD font
//-------------------------------------------------
void osd_font_osx::close()
{
if( m_font != NULL )
{
CFRelease( m_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_font_osx::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
UniChar uni_char;
CGGlyph glyph;
CTFontRef ct_font = m_font;
const CFIndex count = 1;
CGRect bounding_rect, success_rect;
CGContextRef context_ref;
if( chnum == ' ' )
{
uni_char = 'n';
CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
uni_char = chnum;
CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
}
else
{
uni_char = chnum;
CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
}
if( CGRectEqualToRect( success_rect, CGRectNull ) == false )
{
size_t bitmap_width;
size_t bitmap_height;
bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH);
bitmap_width = bitmap_width == 0 ? 1 : bitmap_width;
bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT);
xoffs = yoffs = 0;
width = bitmap_width;
size_t bits_per_component;
CGColorSpaceRef color_space;
CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
color_space = CGColorSpaceCreateDeviceRGB();
bits_per_component = 8;
bitmap.allocate(bitmap_width, bitmap_height);
context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info );
if( context_ref != NULL )
{
CGFontRef font_ref;
font_ref = CTFontCopyGraphicsFont( ct_font, NULL );
CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) );
CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0);
CGContextSetFont( context_ref, font_ref );
CGContextSetFontSize( context_ref, POINT_SIZE );
CGContextShowGlyphs( context_ref, &glyph, count );
CGFontRelease( font_ref );
CGContextRelease( context_ref );
}
CGColorSpaceRelease( color_space );
}
return bitmap.valid();
}

View File

@ -0,0 +1,326 @@
/*
* font_sdl.c
*
*/
#if (SDLMAME_SDL2)
#include <SDL2/SDL_ttf.h>
#else
#include <SDL/SDL_ttf.h>
#endif
#ifndef SDLMAME_HAIKU
#include <fontconfig/fontconfig.h>
#endif
#include "osdepend.h"
#include "astring.h"
#include "corealloc.h"
#include "fileio.h"
#define POINT_SIZE 144.0
//-------------------------------------------------
// font_open - attempt to "open" a handle to the
// font with the given name
//-------------------------------------------------
class osd_font_unix : public osd_font
{
public:
virtual ~osd_font_unix() {};
virtual bool open(const char *font_path, const char *name, int &height);
virtual void close();
virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
private:
#ifndef SDLMAME_HAIKU
TTF_Font *search_font_config(astring name, bool bold, bool italic, bool underline, bool &bakedstyles);
#endif
bool BDF_Check_Magic(astring name);
TTF_Font * TTF_OpenFont_Magic(astring name, int fsize);
TTF_Font *m_font;
};
osd_font *osd_font_alloc()
{
return global_alloc(osd_font_unix);
}
bool osd_font_unix::open(const char *font_path, const char *_name, int &height)
{
TTF_Font *font = (TTF_Font *)NULL;
bool bakedstyles = false;
int style = 0;
// accept qualifiers from the name
astring name(_name);
if (name == "default")
{
name = "Liberation Sans";
}
bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
bool underline = (name.replace(0, "[U]", "") + name.replace(0, "[u]", "") > 0);
bool strike = (name.replace(0, "[S]", "") + name.replace(0, "[s]", "") > 0);
// first up, try it as a filename
font = TTF_OpenFont_Magic(name, POINT_SIZE);
// if no success, try the font path
if (!font)
{
osd_printf_verbose("Searching font %s in -%s\n", name.cstr(), OPTION_FONTPATH);
//emu_file file(options().font_path(), OPEN_FLAG_READ);
emu_file file(font_path, OPEN_FLAG_READ);
if (file.open(name) == FILERR_NONE)
{
astring full_name = file.fullpath();
font = TTF_OpenFont_Magic(full_name, POINT_SIZE);
if (font)
osd_printf_verbose("Found font %s\n", full_name.cstr());
}
}
// if that didn't work, crank up the FontConfig database
#ifndef SDLMAME_HAIKU
if (!font)
{
font = search_font_config(name, bold, italic, underline, bakedstyles);
}
#endif
if (!font)
{
if (!BDF_Check_Magic(name))
{
osd_printf_verbose("font %s is not TrueType or BDF, using MAME default\n", name.cstr());
}
return NULL;
}
// apply styles
if (!bakedstyles)
{
style |= bold ? TTF_STYLE_BOLD : 0;
style |= italic ? TTF_STYLE_ITALIC : 0;
}
style |= underline ? TTF_STYLE_UNDERLINE : 0;
// SDL_ttf 2.0.9 and earlier does not define TTF_STYLE_STRIKETHROUGH
#if SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) > SDL_VERSIONNUM(2,0,9)
style |= strike ? TTF_STYLE_STRIKETHROUGH : 0;
#else
if (strike)
osd_printf_warning("Ignoring strikethrough for SDL_TTF older than 2.0.10\n");
#endif // PATCHLEVEL
TTF_SetFontStyle(font, style);
height = TTF_FontLineSkip(font);
m_font = font;
return true;
}
//-------------------------------------------------
// font_close - release resources associated with
// a given OSD font
//-------------------------------------------------
void osd_font_unix::close()
{
TTF_CloseFont(this->m_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_font_unix::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
TTF_Font *ttffont;
SDL_Surface *drawsurf;
SDL_Color fcol = { 0xff, 0xff, 0xff };
UINT16 ustr[16];
ttffont = m_font;
memset(ustr,0,sizeof(ustr));
ustr[0] = (UINT16)chnum;
drawsurf = TTF_RenderUNICODE_Solid(ttffont, ustr, fcol);
// was nothing returned?
if (drawsurf)
{
// allocate a MAME destination bitmap
bitmap.allocate(drawsurf->w, drawsurf->h);
// 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;
srcrow += (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);
}
}
// what are these?
xoffs = yoffs = 0;
width = drawsurf->w;
SDL_FreeSurface(drawsurf);
}
return bitmap.valid();
}
TTF_Font * osd_font_unix::TTF_OpenFont_Magic(astring name, int fsize)
{
emu_file file(OPEN_FLAG_READ);
if (file.open(name) == FILERR_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 NULL;
}
return TTF_OpenFont(name.cstr(), POINT_SIZE);
}
bool osd_font_unix::BDF_Check_Magic(astring name)
{
emu_file file(OPEN_FLAG_READ);
if (file.open(name) == FILERR_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))
return true;
}
return false;
}
#ifndef SDLMAME_HAIKU
TTF_Font *osd_font_unix::search_font_config(astring name, bool bold, bool italic, bool underline, bool &bakedstyles)
{
TTF_Font *font = (TTF_Font *)NULL;
FcConfig *config;
FcPattern *pat;
FcObjectSet *os;
FcFontSet *fontset;
FcValue val;
config = FcConfigGetCurrent();
pat = FcPatternCreate();
os = FcObjectSetCreate();
FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.cstr());
// try and get a font with the requested styles baked-in
if (bold)
{
if (italic)
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold Italic");
}
else
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold");
}
}
else if (italic)
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Italic");
}
else
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
}
FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
FcObjectSetAdd(os, FC_FILE);
fontset = FcFontList(config, pat, os);
for (int i = 0; i < fontset->nfont; i++)
{
if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
{
continue;
}
if (val.type != FcTypeString)
{
continue;
}
osd_printf_verbose("Matching font: %s\n", val.u.s);
{
astring match_name((const char*)val.u.s);
font = TTF_OpenFont_Magic(match_name, POINT_SIZE);
}
if (font)
{
bakedstyles = true;
break;
}
}
// 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.cstr());
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
fontset = FcFontList(config, pat, os);
for (int i = 0; i < fontset->nfont; i++)
{
if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
{
continue;
}
if (val.type != FcTypeString)
{
continue;
}
osd_printf_verbose("Matching unstyled font: %s\n", val.u.s);
{
astring 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

View File

@ -0,0 +1,300 @@
/*
* font_sdl.c
*
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <mmsystem.h>
#include <tchar.h>
#include <io.h>
#include "osdepend.h"
#include "strconv.h"
#include "astring.h"
#include "corealloc.h"
#include "fileio.h"
//#define POINT_SIZE 144.0
#define DEFAULT_FONT_HEIGHT (200)
#if 0
//============================================================
// wstring_from_utf8
//============================================================
// FIXME: defined in multiple locations ... FIXME
WCHAR *wstring_from_utf8(const char *utf8string)
{
int char_count;
WCHAR *result;
// convert MAME string (UTF-8) to UTF-16
char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0);
result = (WCHAR *)osd_malloc_array(char_count * sizeof(*result));
if (result != NULL)
MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);
return result;
}
//============================================================
// utf8_from_wstring
//============================================================
char *utf8_from_wstring(const WCHAR *wstring)
{
int char_count;
char *result;
// convert UTF-16 to MAME string (UTF-8)
char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL);
result = (char *)osd_malloc_array(char_count * sizeof(*result));
if (result != NULL)
WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL);
return result;
}
#endif
//-------------------------------------------------
// font_open - attempt to "open" a handle to the
// font with the given name
//-------------------------------------------------
class osd_font_windows : public osd_font
{
public:
virtual ~osd_font_windows() {};
virtual bool open(const char *font_path, const char *name, int &height);
virtual void close();
virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
private:
HGDIOBJ m_font;
};
osd_font *osd_font_alloc()
{
return global_alloc(osd_font_windows);
}
bool osd_font_windows::open(const char *font_path, 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;
m_font = CreateFontIndirect(&logfont);
if (m_font == NULL)
return false;
// 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);
SelectObject(dummyDC, oldfont);
DeleteDC(dummyDC);
// if it doesn't match our request, fail
char *utf = utf8_from_tstring(realname);
int result = core_stricmp(utf, name);
osd_free(utf);
// if we didn't match, nuke our font and fall back
if (result != 0)
{
DeleteObject(m_font);
m_font = NULL;
return false;
}
return true;
}
//-------------------------------------------------
// font_close - release resources associated with
// a given OSD font
//-------------------------------------------------
void osd_font_windows::close()
{
// delete the font ojbect
if (m_font != NULL)
DeleteObject(m_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_font_windows::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
// create a dummy DC to work with
HDC dummyDC = CreateCompatibleDC(NULL);
HGDIOBJ oldfont = SelectObject(dummyDC, m_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;
RGBQUAD col1 = info.bmiColors[0];
RGBQUAD col2 = info.bmiColors[1];
col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
col2.rgbBlue = col2.rgbGreen = col2.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
if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
{
bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
// copy the bits into it
for (int y = 0; y < bitmap.height(); y++)
{
UINT32 *dstrow = &bitmap.pix32(y);
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) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(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.valid();
}

View File

@ -26,11 +26,26 @@ class input_type_entry; // FIXME: including emu.h does not work because emu.
// TYPE DEFINITIONS
//============================================================
// FIXME: We can do better than this
class osd_font;
// ======================> osd_font interface
class osd_font
{
public:
virtual ~osd_font() {}
virtual bool open(const char *font_path, const char *name, int &height) = 0;
virtual void close() = 0;
virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) = 0;
};
// ======================> osd_interface
/* FIXME: this should be replaced by a proper module implementation
* For the time being only one font provider can be linked
*/
osd_font *osd_font_alloc();
// description of the currently-running machine
class osd_interface
{
@ -52,14 +67,14 @@ public:
// input overridables
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) = 0;
// font overridables
virtual osd_font *font_open(const char *name, int &height) = 0;
virtual void font_close(osd_font *font) = 0;
virtual bool font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) = 0;
// video overridables
virtual void *get_slider_list() = 0; // FIXME: returns slider_state *
// font interface
// font is allocated with global_alloc; therefore use global_free!
osd_font *font_alloc() { return osd_font_alloc(); }
// command option overrides
virtual bool execute_command(const char *command) = 0;

View File

@ -186,11 +186,6 @@ public:
// input overridables
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist);
// 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);
virtual void video_register();
virtual void sound_register();
virtual void debugger_register();

View File

@ -204,12 +204,14 @@ endif
ifeq ($(TARGETOS),unix)
BASE_TARGETOS = unix
SYNC_IMPLEMENTATION = tc
FONT_IMPLEMENTATION = unix
endif
ifeq ($(TARGETOS),linux)
BASE_TARGETOS = unix
SYNC_IMPLEMENTATION = tc
SDL_NETWORK = taptun
FONT_IMPLEMENTATION = unix
ifndef NO_USE_MIDI
INCPATH += `pkg-config --cflags alsa`
@ -221,6 +223,7 @@ endif
ifeq ($(TARGETOS),freebsd)
BASE_TARGETOS = unix
SYNC_IMPLEMENTATION = tc
FONT_IMPLEMENTATION = unix
DEFS += -DNO_AFFINITY_NP
LIBS += -lutil
# /usr/local/include is not considered a system include directory
@ -232,6 +235,7 @@ endif
ifeq ($(TARGETOS),openbsd)
BASE_TARGETOS = unix
SYNC_IMPLEMENTATION = ntc
FONT_IMPLEMENTATION = unix
LIBS += -lutil
NO_USE_MIDI = 1
endif
@ -239,6 +243,7 @@ endif
ifeq ($(TARGETOS),netbsd)
BASE_TARGETOS = unix
SYNC_IMPLEMENTATION = ntc
FONT_IMPLEMENTATION = unix
LIBS += -lutil
NO_USE_MIDI = 1
endif
@ -247,12 +252,14 @@ ifeq ($(TARGETOS),solaris)
BASE_TARGETOS = unix
DEFS += -DNO_AFFINITY_NP -UHAVE_VSNPRINTF -DNO_vsnprintf
SYNC_IMPLEMENTATION = tc
FONT_IMPLEMENTATION = unix
NO_USE_MIDI = 1
endif
ifeq ($(TARGETOS),haiku)
BASE_TARGETOS = unix
SYNC_IMPLEMENTATION = ntc
FONT_IMPLEMENTATION = unix
NO_X11 = 1
NO_USE_XINPUT = 1
NO_USE_MIDI = 1
@ -263,6 +270,7 @@ endif
ifeq ($(TARGETOS),emscripten)
BASE_TARGETOS = unix
SYNC_IMPLEMENTATION = mini
FONT_IMPLEMENTATION = none
NO_DEBUGGER = 1
NO_X11 = 1
NO_USE_XINPUT = 1
@ -274,6 +282,7 @@ endif
ifeq ($(TARGETOS),macosx)
NO_USE_QTDEBUG = 1
BASE_TARGETOS = unix
FONT_IMPLEMENTATION = osx
DEFS += -DSDLMAME_UNIX -DSDLMAME_MACOSX -DSDLMAME_DARWIN
ifndef NO_USE_MIDI
@ -326,6 +335,7 @@ endif
ifeq ($(TARGETOS),win32)
BASE_TARGETOS = win32
SYNC_IMPLEMENTATION = windows
FONT_IMPLEMENTATION = windows
NO_X11 = 1
NO_USE_XINPUT = 1
DEFS += -DSDLMAME_WIN32 -DX64_WINDOWS_ABI
@ -363,6 +373,7 @@ ifeq ($(TARGETOS),os2)
BASE_TARGETOS = os2
DEFS += -DSDLMAME_OS2
SYNC_IMPLEMENTATION = os2
FONT_IMPLEMENTATION = none
NO_DEBUGGER = 1
NO_X11 = 1
NO_USE_XINPUT = 1
@ -387,6 +398,11 @@ NO_DEBUGGER = 1
endif
endif
ifndef FONT_IMPLEMENTATION
$(error Please define FONT_IMPLEMENTATION !)
endif
#-------------------------------------------------
# object and source roots
#-------------------------------------------------
@ -398,6 +414,7 @@ OBJDIRS += $(SDLOBJ) \
$(OSDOBJ)/modules/sync \
$(OSDOBJ)/modules/lib \
$(OSDOBJ)/modules/midi \
$(OSDOBJ)/modules/font \
#-------------------------------------------------
# OSD core library
@ -412,7 +429,8 @@ OSDCOREOBJS = \
$(SDLOBJ)/sdlmisc_$(BASE_TARGETOS).o \
$(SDLOBJ)/sdlos_$(SDLOS_TARGETOS).o \
$(OSDOBJ)/modules/lib/osdlib_$(SDLOS_TARGETOS).o \
$(OSDOBJ)/modules/sync/sync_$(SYNC_IMPLEMENTATION).o
$(OSDOBJ)/modules/sync/sync_$(SYNC_IMPLEMENTATION).o \
$(OSDOBJ)/modules/font/font_$(FONT_IMPLEMENTATION).o \
ifdef NOASM
OSDCOREOBJS += $(OSDOBJ)/modules/sync/work_mini.o

View File

@ -85,8 +85,6 @@
#include "watchdog.h"
#define DEFAULT_FONT_HEIGHT (200)
//============================================================
// OPTIONS
//============================================================
@ -303,6 +301,7 @@ int main(int argc, char *argv[])
setvbuf(stdout, (char *) NULL, _IONBF, 0);
setvbuf(stderr, (char *) NULL, _IONBF, 0);
//FIXME: move to font module
#ifdef SDLMAME_UNIX
sdl_entered_debugger = 0;
#if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN))
@ -712,466 +711,6 @@ void sdl_osd_interface::init(running_machine &machine)
#endif
}
#if defined(SDLMAME_UNIX) && (!defined(SDLMAME_EMSCRIPTEN))
#define POINT_SIZE 144.0
#ifdef SDLMAME_MACOSX
#define EXTRA_HEIGHT 1.0
#define EXTRA_WIDTH 1.15
//-------------------------------------------------
// font_open - attempt to "open" a handle to the
// font with the given name
//-------------------------------------------------
class osd_font
{
public:
CTFontRef m_font;
};
osd_font *sdl_osd_interface::font_open(const char *_name, int &height)
{
CFStringRef font_name = NULL;
CTFontRef ct_font = NULL;
CTFontDescriptorRef font_descriptor;
CGAffineTransform affine_transform = CGAffineTransformIdentity;
astring name(_name);
if (name == "default")
{
name = "LucidaGrande";
}
/* handle bdf fonts in the core */
if (name.len() > 4)
if (name.makeupper().substr(name.len()-4,4) == ".BDF" )
return NULL;
font_name = CFStringCreateWithCString( NULL, name.cstr(), kCFStringEncodingUTF8 );
if( font_name != NULL )
{
font_descriptor = CTFontDescriptorCreateWithNameAndSize( font_name, POINT_SIZE );
if( font_descriptor != NULL )
{
ct_font = CTFontCreateWithFontDescriptor( font_descriptor, POINT_SIZE, &affine_transform );
CFRelease( font_descriptor );
}
}
CFRelease( font_name );
if (!ct_font)
{
osd_printf_verbose("Couldn't find/open font %s, using MAME default\n", name.cstr());
return NULL;
}
CFStringRef real_name = CTFontCopyPostScriptName( ct_font );
char real_name_c_string[255];
CFStringGetCString ( real_name, real_name_c_string, 255, kCFStringEncodingUTF8 );
osd_printf_verbose("Matching font: %s\n", real_name_c_string);
CFRelease( real_name );
CGFloat line_height = 0.0;
line_height += CTFontGetAscent(ct_font);
line_height += CTFontGetDescent(ct_font);
line_height += CTFontGetLeading(ct_font);
height = ceilf(line_height * EXTRA_HEIGHT);
osd_font *ret = global_alloc(osd_font);
ret->m_font = ct_font;
return ret;
}
//-------------------------------------------------
// font_close - release resources associated with
// a given OSD font
//-------------------------------------------------
void sdl_osd_interface::font_close(osd_font *font)
{
CTFontRef ct_font = font->m_font;
if( ct_font != NULL )
{
CFRelease( ct_font );
}
global_free(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 sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
UniChar uni_char;
CGGlyph glyph;
CTFontRef ct_font = font->m_font;
const CFIndex count = 1;
CGRect bounding_rect, success_rect;
CGContextRef context_ref;
if( chnum == ' ' )
{
uni_char = 'n';
CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
uni_char = chnum;
CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
}
else
{
uni_char = chnum;
CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
}
if( CGRectEqualToRect( success_rect, CGRectNull ) == false )
{
size_t bitmap_width;
size_t bitmap_height;
bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH);
bitmap_width = bitmap_width == 0 ? 1 : bitmap_width;
bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT);
xoffs = yoffs = 0;
width = bitmap_width;
size_t bits_per_component;
CGColorSpaceRef color_space;
CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
color_space = CGColorSpaceCreateDeviceRGB();
bits_per_component = 8;
bitmap.allocate(bitmap_width, bitmap_height);
context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info );
if( context_ref != NULL )
{
CGFontRef font_ref;
font_ref = CTFontCopyGraphicsFont( ct_font, NULL );
CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) );
CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0);
CGContextSetFont( context_ref, font_ref );
CGContextSetFontSize( context_ref, POINT_SIZE );
CGContextShowGlyphs( context_ref, &glyph, count );
CGFontRelease( font_ref );
CGContextRelease( context_ref );
}
CGColorSpaceRelease( color_space );
}
return bitmap.valid();
}
#else // UNIX but not OSX
static TTF_Font * TTF_OpenFont_Magic(astring name, int fsize)
{
emu_file file(OPEN_FLAG_READ);
if (file.open(name) == FILERR_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 NULL;
}
return TTF_OpenFont(name.cstr(), POINT_SIZE);
}
static bool BDF_Check_Magic(astring name)
{
emu_file file(OPEN_FLAG_READ);
if (file.open(name) == FILERR_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))
return true;
}
return false;
}
#ifndef SDLMAME_HAIKU
static TTF_Font *search_font_config(astring name, bool bold, bool italic, bool underline, bool &bakedstyles)
{
TTF_Font *font = (TTF_Font *)NULL;
FcConfig *config;
FcPattern *pat;
FcObjectSet *os;
FcFontSet *fontset;
FcValue val;
config = FcConfigGetCurrent();
pat = FcPatternCreate();
os = FcObjectSetCreate();
FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.cstr());
// try and get a font with the requested styles baked-in
if (bold)
{
if (italic)
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold Italic");
}
else
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold");
}
}
else if (italic)
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Italic");
}
else
{
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
}
FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
FcObjectSetAdd(os, FC_FILE);
fontset = FcFontList(config, pat, os);
for (int i = 0; i < fontset->nfont; i++)
{
if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
{
continue;
}
if (val.type != FcTypeString)
{
continue;
}
osd_printf_verbose("Matching font: %s\n", val.u.s);
{
astring match_name((const char*)val.u.s);
font = TTF_OpenFont_Magic(match_name, POINT_SIZE);
}
if (font)
{
bakedstyles = true;
break;
}
}
// 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.cstr());
FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
fontset = FcFontList(config, pat, os);
for (int i = 0; i < fontset->nfont; i++)
{
if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
{
continue;
}
if (val.type != FcTypeString)
{
continue;
}
osd_printf_verbose("Matching unstyled font: %s\n", val.u.s);
{
astring 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
//-------------------------------------------------
// font_open - attempt to "open" a handle to the
// font with the given name
//-------------------------------------------------
class osd_font
{
public:
TTF_Font *m_font;
};
osd_font *sdl_osd_interface::font_open(const char *_name, int &height)
{
TTF_Font *font = (TTF_Font *)NULL;
bool bakedstyles = false;
int style = 0;
// accept qualifiers from the name
astring name(_name);
if (name == "default")
{
name = "Liberation Sans";
}
bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
bool underline = (name.replace(0, "[U]", "") + name.replace(0, "[u]", "") > 0);
bool strike = (name.replace(0, "[S]", "") + name.replace(0, "[s]", "") > 0);
// first up, try it as a filename
font = TTF_OpenFont_Magic(name, POINT_SIZE);
// if no success, try the font path
if (!font)
{
osd_printf_verbose("Searching font %s in -%s\n", name.cstr(), OPTION_FONTPATH);
emu_file file(options().font_path(), OPEN_FLAG_READ);
if (file.open(name) == FILERR_NONE)
{
astring full_name = file.fullpath();
font = TTF_OpenFont_Magic(full_name, POINT_SIZE);
if (font)
osd_printf_verbose("Found font %s\n", full_name.cstr());
}
}
// if that didn't work, crank up the FontConfig database
#ifndef SDLMAME_HAIKU
if (!font)
{
font = search_font_config(name, bold, italic, underline, bakedstyles);
}
#endif
if (!font)
{
if (!BDF_Check_Magic(name))
{
osd_printf_verbose("font %s is not TrueType or BDF, using MAME default\n", name.cstr());
}
return NULL;
}
// apply styles
if (!bakedstyles)
{
style |= bold ? TTF_STYLE_BOLD : 0;
style |= italic ? TTF_STYLE_ITALIC : 0;
}
style |= underline ? TTF_STYLE_UNDERLINE : 0;
// SDL_ttf 2.0.9 and earlier does not define TTF_STYLE_STRIKETHROUGH
#if SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) > SDL_VERSIONNUM(2,0,9)
style |= strike ? TTF_STYLE_STRIKETHROUGH : 0;
#else
if (strike)
osd_printf_warning("Ignoring strikethrough for SDL_TTF older than 2.0.10\n");
#endif // PATCHLEVEL
TTF_SetFontStyle(font, style);
height = TTF_FontLineSkip(font);
osd_font *ret = global_alloc(osd_font);
ret->m_font = font;
return ret;
}
//-------------------------------------------------
// font_close - release resources associated with
// a given OSD font
//-------------------------------------------------
void sdl_osd_interface::font_close(osd_font *font)
{
TTF_CloseFont(font->m_font);
global_free(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 sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
TTF_Font *ttffont;
SDL_Surface *drawsurf;
SDL_Color fcol = { 0xff, 0xff, 0xff };
UINT16 ustr[16];
ttffont = font->m_font;
memset(ustr,0,sizeof(ustr));
ustr[0] = (UINT16)chnum;
drawsurf = TTF_RenderUNICODE_Solid(ttffont, ustr, fcol);
// was nothing returned?
if (drawsurf)
{
// allocate a MAME destination bitmap
bitmap.allocate(drawsurf->w, drawsurf->h);
// 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;
srcrow += (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);
}
}
// what are these?
xoffs = yoffs = 0;
width = drawsurf->w;
SDL_FreeSurface(drawsurf);
}
return bitmap.valid();
}
#endif // not OSX
#else // not UNIX
#ifdef SDLMAME_WIN32
//============================================================
@ -1211,255 +750,6 @@ char *utf8_from_wstring(const WCHAR *wstring)
return result;
}
osd_font *sdl_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 = core_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 sdl_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 rgb_t(0xff,0xff,0xff,0xff)
// or rgb_t(0x00,0xff,0xff,0xff) for each
// pixel of a black & white font
//-------------------------------------------------
bool sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, 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;
RGBQUAD col1 = info.bmiColors[0];
RGBQUAD col2 = info.bmiColors[1];
col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
col2.rgbBlue = col2.rgbGreen = col2.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
if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
{
bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
// copy the bits into it
for (int y = 0; y < bitmap.height(); y++)
{
UINT32 *dstrow = &bitmap.pix32(y);
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) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(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.valid();
}
#else
//-------------------------------------------------
// font_open - attempt to "open" a handle to the
// font with the given name
//-------------------------------------------------
osd_font *sdl_osd_interface::font_open(const char *_name, int &height)
{
return (osd_font *)NULL;
}
//-------------------------------------------------
// font_close - release resources associated with
// a given OSD font
//-------------------------------------------------
void sdl_osd_interface::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 sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
return false;
}
#endif
#endif

View File

@ -91,6 +91,7 @@ OBJDIRS += $(WINOBJ) \
$(OSDOBJ)/modules/sync \
$(OSDOBJ)/modules/lib \
$(OSDOBJ)/modules/midi \
$(OSDOBJ)/modules/font \
ifdef USE_QTDEBUG
OBJDIRS += $(OSDOBJ)/modules/debugger/qt
@ -356,6 +357,7 @@ OSDCOREOBJS = \
$(WINOBJ)/winsocket.o \
$(OSDOBJ)/modules/sync/work_osd.o \
$(OSDOBJ)/modules/lib/osdlib_win32.o \
$(OSDOBJ)/modules/font/font_windows.o \
$(WINOBJ)/winptty.o \

View File

@ -713,228 +713,6 @@ void windows_osd_interface::osd_exit()
winwindow_process_events(machine(), 0, 0);
}
//-------------------------------------------------
// 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 = core_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 rgb_t(0xff,0xff,0xff,0xff)
// or rgb_t(0x00,0xff,0xff,0xff) for each
// pixel of a black & white font
//-------------------------------------------------
bool windows_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, 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;
RGBQUAD col1 = info.bmiColors[0];
RGBQUAD col2 = info.bmiColors[1];
col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
col2.rgbBlue = col2.rgbGreen = col2.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
if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
{
bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
// copy the bits into it
for (int y = 0; y < bitmap.height(); y++)
{
UINT32 *dstrow = &bitmap.pix32(y);
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) ? rgb_t(0xff,0xff,0xff,0xff) : rgb_t(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.valid();
}
//============================================================
// winmain_dump_stack
//============================================================

View File

@ -252,11 +252,6 @@ public:
// input overridables
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist);
// 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);
virtual void video_register();
virtual void sound_register();
virtual void debugger_register();