mirror of
https://github.com/holub/mame
synced 2025-05-25 07:15:25 +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 this is an OSD font, we're done
|
||||||
if (filename != NULL)
|
if (filename != NULL)
|
||||||
{
|
{
|
||||||
m_osdfont = manager.machine().osd().font_open(filename, m_height);
|
m_osdfont = manager.machine().osd().font_alloc();
|
||||||
if (m_osdfont != NULL)
|
if (m_osdfont != NULL)
|
||||||
{
|
{
|
||||||
m_scale = 1.0f / (float)m_height;
|
if (m_osdfont->open(manager.machine().options().font_path(), filename, m_height))
|
||||||
m_format = FF_OSD;
|
{
|
||||||
return;
|
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
|
// release the OSD font
|
||||||
if (m_osdfont != NULL)
|
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;
|
return;
|
||||||
|
|
||||||
// attempt to get the font bitmap; if we fail, set bmwidth to -1
|
// 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.bitmap.reset();
|
||||||
gl.bmwidth = -1;
|
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
|
// TYPE DEFINITIONS
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
// FIXME: We can do better than this
|
// ======================> osd_font interface
|
||||||
class osd_font;
|
|
||||||
|
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
|
// ======================> 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
|
// description of the currently-running machine
|
||||||
class osd_interface
|
class osd_interface
|
||||||
{
|
{
|
||||||
@ -52,14 +67,14 @@ public:
|
|||||||
// input overridables
|
// input overridables
|
||||||
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) = 0;
|
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
|
// video overridables
|
||||||
virtual void *get_slider_list() = 0; // FIXME: returns slider_state *
|
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
|
// command option overrides
|
||||||
virtual bool execute_command(const char *command) = 0;
|
virtual bool execute_command(const char *command) = 0;
|
||||||
|
|
||||||
|
@ -186,11 +186,6 @@ public:
|
|||||||
// input overridables
|
// input overridables
|
||||||
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist);
|
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 video_register();
|
||||||
virtual void sound_register();
|
virtual void sound_register();
|
||||||
virtual void debugger_register();
|
virtual void debugger_register();
|
||||||
|
@ -204,12 +204,14 @@ endif
|
|||||||
ifeq ($(TARGETOS),unix)
|
ifeq ($(TARGETOS),unix)
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
SYNC_IMPLEMENTATION = tc
|
SYNC_IMPLEMENTATION = tc
|
||||||
|
FONT_IMPLEMENTATION = unix
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGETOS),linux)
|
ifeq ($(TARGETOS),linux)
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
SYNC_IMPLEMENTATION = tc
|
SYNC_IMPLEMENTATION = tc
|
||||||
SDL_NETWORK = taptun
|
SDL_NETWORK = taptun
|
||||||
|
FONT_IMPLEMENTATION = unix
|
||||||
|
|
||||||
ifndef NO_USE_MIDI
|
ifndef NO_USE_MIDI
|
||||||
INCPATH += `pkg-config --cflags alsa`
|
INCPATH += `pkg-config --cflags alsa`
|
||||||
@ -221,6 +223,7 @@ endif
|
|||||||
ifeq ($(TARGETOS),freebsd)
|
ifeq ($(TARGETOS),freebsd)
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
SYNC_IMPLEMENTATION = tc
|
SYNC_IMPLEMENTATION = tc
|
||||||
|
FONT_IMPLEMENTATION = unix
|
||||||
DEFS += -DNO_AFFINITY_NP
|
DEFS += -DNO_AFFINITY_NP
|
||||||
LIBS += -lutil
|
LIBS += -lutil
|
||||||
# /usr/local/include is not considered a system include directory
|
# /usr/local/include is not considered a system include directory
|
||||||
@ -232,6 +235,7 @@ endif
|
|||||||
ifeq ($(TARGETOS),openbsd)
|
ifeq ($(TARGETOS),openbsd)
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
SYNC_IMPLEMENTATION = ntc
|
SYNC_IMPLEMENTATION = ntc
|
||||||
|
FONT_IMPLEMENTATION = unix
|
||||||
LIBS += -lutil
|
LIBS += -lutil
|
||||||
NO_USE_MIDI = 1
|
NO_USE_MIDI = 1
|
||||||
endif
|
endif
|
||||||
@ -239,6 +243,7 @@ endif
|
|||||||
ifeq ($(TARGETOS),netbsd)
|
ifeq ($(TARGETOS),netbsd)
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
SYNC_IMPLEMENTATION = ntc
|
SYNC_IMPLEMENTATION = ntc
|
||||||
|
FONT_IMPLEMENTATION = unix
|
||||||
LIBS += -lutil
|
LIBS += -lutil
|
||||||
NO_USE_MIDI = 1
|
NO_USE_MIDI = 1
|
||||||
endif
|
endif
|
||||||
@ -247,12 +252,14 @@ ifeq ($(TARGETOS),solaris)
|
|||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
DEFS += -DNO_AFFINITY_NP -UHAVE_VSNPRINTF -DNO_vsnprintf
|
DEFS += -DNO_AFFINITY_NP -UHAVE_VSNPRINTF -DNO_vsnprintf
|
||||||
SYNC_IMPLEMENTATION = tc
|
SYNC_IMPLEMENTATION = tc
|
||||||
|
FONT_IMPLEMENTATION = unix
|
||||||
NO_USE_MIDI = 1
|
NO_USE_MIDI = 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGETOS),haiku)
|
ifeq ($(TARGETOS),haiku)
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
SYNC_IMPLEMENTATION = ntc
|
SYNC_IMPLEMENTATION = ntc
|
||||||
|
FONT_IMPLEMENTATION = unix
|
||||||
NO_X11 = 1
|
NO_X11 = 1
|
||||||
NO_USE_XINPUT = 1
|
NO_USE_XINPUT = 1
|
||||||
NO_USE_MIDI = 1
|
NO_USE_MIDI = 1
|
||||||
@ -263,6 +270,7 @@ endif
|
|||||||
ifeq ($(TARGETOS),emscripten)
|
ifeq ($(TARGETOS),emscripten)
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
SYNC_IMPLEMENTATION = mini
|
SYNC_IMPLEMENTATION = mini
|
||||||
|
FONT_IMPLEMENTATION = none
|
||||||
NO_DEBUGGER = 1
|
NO_DEBUGGER = 1
|
||||||
NO_X11 = 1
|
NO_X11 = 1
|
||||||
NO_USE_XINPUT = 1
|
NO_USE_XINPUT = 1
|
||||||
@ -274,6 +282,7 @@ endif
|
|||||||
ifeq ($(TARGETOS),macosx)
|
ifeq ($(TARGETOS),macosx)
|
||||||
NO_USE_QTDEBUG = 1
|
NO_USE_QTDEBUG = 1
|
||||||
BASE_TARGETOS = unix
|
BASE_TARGETOS = unix
|
||||||
|
FONT_IMPLEMENTATION = osx
|
||||||
DEFS += -DSDLMAME_UNIX -DSDLMAME_MACOSX -DSDLMAME_DARWIN
|
DEFS += -DSDLMAME_UNIX -DSDLMAME_MACOSX -DSDLMAME_DARWIN
|
||||||
|
|
||||||
ifndef NO_USE_MIDI
|
ifndef NO_USE_MIDI
|
||||||
@ -326,6 +335,7 @@ endif
|
|||||||
ifeq ($(TARGETOS),win32)
|
ifeq ($(TARGETOS),win32)
|
||||||
BASE_TARGETOS = win32
|
BASE_TARGETOS = win32
|
||||||
SYNC_IMPLEMENTATION = windows
|
SYNC_IMPLEMENTATION = windows
|
||||||
|
FONT_IMPLEMENTATION = windows
|
||||||
NO_X11 = 1
|
NO_X11 = 1
|
||||||
NO_USE_XINPUT = 1
|
NO_USE_XINPUT = 1
|
||||||
DEFS += -DSDLMAME_WIN32 -DX64_WINDOWS_ABI
|
DEFS += -DSDLMAME_WIN32 -DX64_WINDOWS_ABI
|
||||||
@ -363,6 +373,7 @@ ifeq ($(TARGETOS),os2)
|
|||||||
BASE_TARGETOS = os2
|
BASE_TARGETOS = os2
|
||||||
DEFS += -DSDLMAME_OS2
|
DEFS += -DSDLMAME_OS2
|
||||||
SYNC_IMPLEMENTATION = os2
|
SYNC_IMPLEMENTATION = os2
|
||||||
|
FONT_IMPLEMENTATION = none
|
||||||
NO_DEBUGGER = 1
|
NO_DEBUGGER = 1
|
||||||
NO_X11 = 1
|
NO_X11 = 1
|
||||||
NO_USE_XINPUT = 1
|
NO_USE_XINPUT = 1
|
||||||
@ -387,6 +398,11 @@ NO_DEBUGGER = 1
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifndef FONT_IMPLEMENTATION
|
||||||
|
$(error Please define FONT_IMPLEMENTATION !)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
# object and source roots
|
# object and source roots
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
@ -398,6 +414,7 @@ OBJDIRS += $(SDLOBJ) \
|
|||||||
$(OSDOBJ)/modules/sync \
|
$(OSDOBJ)/modules/sync \
|
||||||
$(OSDOBJ)/modules/lib \
|
$(OSDOBJ)/modules/lib \
|
||||||
$(OSDOBJ)/modules/midi \
|
$(OSDOBJ)/modules/midi \
|
||||||
|
$(OSDOBJ)/modules/font \
|
||||||
|
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
# OSD core library
|
# OSD core library
|
||||||
@ -412,7 +429,8 @@ OSDCOREOBJS = \
|
|||||||
$(SDLOBJ)/sdlmisc_$(BASE_TARGETOS).o \
|
$(SDLOBJ)/sdlmisc_$(BASE_TARGETOS).o \
|
||||||
$(SDLOBJ)/sdlos_$(SDLOS_TARGETOS).o \
|
$(SDLOBJ)/sdlos_$(SDLOS_TARGETOS).o \
|
||||||
$(OSDOBJ)/modules/lib/osdlib_$(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
|
ifdef NOASM
|
||||||
OSDCOREOBJS += $(OSDOBJ)/modules/sync/work_mini.o
|
OSDCOREOBJS += $(OSDOBJ)/modules/sync/work_mini.o
|
||||||
|
@ -85,8 +85,6 @@
|
|||||||
|
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
|
|
||||||
#define DEFAULT_FONT_HEIGHT (200)
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// OPTIONS
|
// OPTIONS
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -303,6 +301,7 @@ int main(int argc, char *argv[])
|
|||||||
setvbuf(stdout, (char *) NULL, _IONBF, 0);
|
setvbuf(stdout, (char *) NULL, _IONBF, 0);
|
||||||
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
setvbuf(stderr, (char *) NULL, _IONBF, 0);
|
||||||
|
|
||||||
|
//FIXME: move to font module
|
||||||
#ifdef SDLMAME_UNIX
|
#ifdef SDLMAME_UNIX
|
||||||
sdl_entered_debugger = 0;
|
sdl_entered_debugger = 0;
|
||||||
#if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN))
|
#if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN))
|
||||||
@ -712,466 +711,6 @@ void sdl_osd_interface::init(running_machine &machine)
|
|||||||
#endif
|
#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
|
#ifdef SDLMAME_WIN32
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
@ -1211,255 +750,6 @@ char *utf8_from_wstring(const WCHAR *wstring)
|
|||||||
return result;
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ OBJDIRS += $(WINOBJ) \
|
|||||||
$(OSDOBJ)/modules/sync \
|
$(OSDOBJ)/modules/sync \
|
||||||
$(OSDOBJ)/modules/lib \
|
$(OSDOBJ)/modules/lib \
|
||||||
$(OSDOBJ)/modules/midi \
|
$(OSDOBJ)/modules/midi \
|
||||||
|
$(OSDOBJ)/modules/font \
|
||||||
|
|
||||||
ifdef USE_QTDEBUG
|
ifdef USE_QTDEBUG
|
||||||
OBJDIRS += $(OSDOBJ)/modules/debugger/qt
|
OBJDIRS += $(OSDOBJ)/modules/debugger/qt
|
||||||
@ -356,6 +357,7 @@ OSDCOREOBJS = \
|
|||||||
$(WINOBJ)/winsocket.o \
|
$(WINOBJ)/winsocket.o \
|
||||||
$(OSDOBJ)/modules/sync/work_osd.o \
|
$(OSDOBJ)/modules/sync/work_osd.o \
|
||||||
$(OSDOBJ)/modules/lib/osdlib_win32.o \
|
$(OSDOBJ)/modules/lib/osdlib_win32.o \
|
||||||
|
$(OSDOBJ)/modules/font/font_windows.o \
|
||||||
$(WINOBJ)/winptty.o \
|
$(WINOBJ)/winptty.o \
|
||||||
|
|
||||||
|
|
||||||
|
@ -713,228 +713,6 @@ void windows_osd_interface::osd_exit()
|
|||||||
winwindow_process_events(machine(), 0, 0);
|
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
|
// winmain_dump_stack
|
||||||
//============================================================
|
//============================================================
|
||||||
|
@ -252,11 +252,6 @@ public:
|
|||||||
// input overridables
|
// input overridables
|
||||||
virtual void customize_input_type_list(simple_list<input_type_entry> &typelist);
|
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 video_register();
|
||||||
virtual void sound_register();
|
virtual void sound_register();
|
||||||
virtual void debugger_register();
|
virtual void debugger_register();
|
||||||
|
Loading…
Reference in New Issue
Block a user