mirror of
https://github.com/holub/mame
synced 2025-05-23 22:20:01 +03:00
Moved font code into osd/modules/font. Extended osd_font to a proper
interface. (nw)
This commit is contained in:
parent
f07d274ac7
commit
a80f04072d
@ -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;
|
||||
|
58
src/osd/modules/font/font_none.c
Normal file
58
src/osd/modules/font/font_none.c
Normal 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;
|
||||
}
|
185
src/osd/modules/font/font_osx.c
Normal file
185
src/osd/modules/font/font_osx.c
Normal 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();
|
||||
}
|
||||
|
326
src/osd/modules/font/font_unix.c
Normal file
326
src/osd/modules/font/font_unix.c
Normal 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
|
300
src/osd/modules/font/font_windows.c
Normal file
300
src/osd/modules/font/font_windows.c
Normal 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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 \
|
||||
|
||||
|
||||
|
@ -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
|
||||
//============================================================
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user