Previous 199869 Revisions Next

r34499 Monday 19th January, 2015 at 20:47:09 UTC by Couriersud
Moved font code into osd/modules/font. Extended osd_font to a proper
interface. (nw)
[src/emu]rendfont.c
[src/osd]osdepend.h
[src/osd/modules/font]font_none.c* font_osx.c* font_unix.c* font_windows.c*
[src/osd/sdl]osdsdl.h sdl.mak sdlmain.c
[src/osd/windows]windows.mak winmain.c winmain.h

trunk/src/emu/rendfont.c
r243010r243011
8989   // if this is an OSD font, we're done
9090   if (filename != NULL)
9191   {
92      m_osdfont = manager.machine().osd().font_open(filename, m_height);
92      m_osdfont = manager.machine().osd().font_alloc();
9393      if (m_osdfont != NULL)
9494      {
95         m_scale = 1.0f / (float)m_height;
96         m_format = FF_OSD;
97         return;
95          if (m_osdfont->open(manager.machine().options().font_path(), filename, m_height))
96          {
97               m_scale = 1.0f / (float)m_height;
98               m_format = FF_OSD;
99               return;
100          }
101          global_free(m_osdfont);
102          m_osdfont = NULL;
98103      }
99104   }
100105
r243010r243011
130135
131136   // release the OSD font
132137   if (m_osdfont != NULL)
133      m_manager.machine().osd().font_close(m_osdfont);
138   {
139        m_osdfont->close();
140        global_free(m_osdfont);
141   }
134142}
135143
136144
r243010r243011
149157         return;
150158
151159      // attempt to get the font bitmap; if we fail, set bmwidth to -1
152      if (!m_manager.machine().osd().font_get_bitmap(m_osdfont, chnum, gl.bitmap, gl.width, gl.xoffs, gl.yoffs))
160      if (!m_osdfont->get_bitmap(chnum, gl.bitmap, gl.width, gl.xoffs, gl.yoffs))
153161      {
154162         gl.bitmap.reset();
155163         gl.bmwidth = -1;
trunk/src/osd/modules/font/font_none.c
r0r243011
1/*
2 * font_sdl.c
3 *
4 */
5
6#include "osdepend.h"
7
8#include "astring.h"
9#include "corealloc.h"
10#include "fileio.h"
11
12//-------------------------------------------------
13//  font_open - attempt to "open" a handle to the
14//  font with the given name
15//-------------------------------------------------
16
17class osd_font_none : public osd_font
18{
19public:
20    virtual ~osd_font_none() {};
21
22    virtual bool open(const char *font_path, const char *name, int &height);
23    virtual void close();
24    virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
25private:
26};
27
28osd_font *osd_font_alloc()
29{
30    return global_alloc(osd_font_none);
31}
32
33bool osd_font_none::open(const char *font_path, const char *_name, int &height)
34{
35    return false;
36}
37
38//-------------------------------------------------
39//  font_close - release resources associated with
40//  a given OSD font
41//-------------------------------------------------
42
43void osd_font_none::close()
44{
45}
46
47//-------------------------------------------------
48//  font_get_bitmap - allocate and populate a
49//  BITMAP_FORMAT_ARGB32 bitmap containing the
50//  pixel values rgb_t(0xff,0xff,0xff,0xff)
51//  or rgb_t(0x00,0xff,0xff,0xff) for each
52//  pixel of a black & white font
53//-------------------------------------------------
54
55bool osd_font_none::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
56{
57    return false;
58}
trunk/src/osd/modules/font/font_osx.c
r0r243011
1/*
2 * font_sdl.c
3 *
4 */
5
6#include <Carbon/Carbon.h>
7
8#include "osdepend.h"
9
10#include "astring.h"
11#include "corealloc.h"
12#include "fileio.h"
13
14#define POINT_SIZE 144.0
15#define EXTRA_HEIGHT 1.0
16#define EXTRA_WIDTH 1.15
17
18//-------------------------------------------------
19//  font_open - attempt to "open" a handle to the
20//  font with the given name
21//-------------------------------------------------
22
23class osd_font_osx : public osd_font
24{
25public:
26    virtual ~osd_font_osx() {};
27
28    virtual bool open(const char *font_path, const char *name, int &height);
29    virtual void close();
30    virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
31private:
32    CTFontRef m_font;
33};
34
35osd_font *osd_font_alloc()
36{
37    return global_alloc(osd_font_osx);
38}
39
40bool osd_font_osx::open(const char *font_path, const char *_name, int &height)
41{
42    CFStringRef font_name = NULL;
43    CTFontRef ct_font = NULL;
44    CTFontDescriptorRef font_descriptor;
45    CGAffineTransform affine_transform = CGAffineTransformIdentity;
46
47    m_font = NULL;
48    astring name(_name);
49    printf("FONT NAME %s\n", _name);
50#if 0
51    if (name == "default")
52    {
53        name = "LucidaGrande";
54    }
55#endif
56    /* handle bdf fonts in the core */
57    if (name.len() > 4)
58        if (name.makeupper().substr(name.len()-4,4) == ".BDF" )
59            return false;
60
61    font_name = CFStringCreateWithCString( NULL, name.cstr(), kCFStringEncodingUTF8 );
62    if( font_name != NULL )
63    {
64        font_descriptor = CTFontDescriptorCreateWithNameAndSize( font_name, 0.0); //POINT_SIZE );
65
66        if( font_descriptor != NULL )
67        {
68            ct_font = CTFontCreateWithFontDescriptor( font_descriptor, POINT_SIZE, &affine_transform );
69
70            CFRelease( font_descriptor );
71        }
72    }
73
74    CFRelease( font_name );
75
76    if (!ct_font)
77    {
78        osd_printf_verbose("Couldn't find/open font %s, using MAME default\n", name.cstr());
79        return false;
80    }
81
82    CFStringRef real_name = CTFontCopyPostScriptName( ct_font );
83    char real_name_c_string[255];
84    CFStringGetCString ( real_name, real_name_c_string, 255, kCFStringEncodingUTF8 );
85    osd_printf_verbose("Matching font: %s\n", real_name_c_string);
86    CFRelease( real_name );
87
88    CGFloat line_height = 0.0;
89    line_height += CTFontGetAscent(ct_font);
90    line_height += CTFontGetDescent(ct_font);
91    line_height += CTFontGetLeading(ct_font);
92    height = ceilf(line_height * EXTRA_HEIGHT);
93
94    m_font = ct_font;
95    return true;
96}
97
98//-------------------------------------------------
99//  font_close - release resources associated with
100//  a given OSD font
101//-------------------------------------------------
102
103void osd_font_osx::close()
104{
105    if( m_font != NULL )
106    {
107        CFRelease( m_font );
108    }
109}
110
111//-------------------------------------------------
112//  font_get_bitmap - allocate and populate a
113//  BITMAP_FORMAT_ARGB32 bitmap containing the
114//  pixel values rgb_t(0xff,0xff,0xff,0xff)
115//  or rgb_t(0x00,0xff,0xff,0xff) for each
116//  pixel of a black & white font
117//-------------------------------------------------
118
119bool osd_font_osx::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
120{
121    UniChar uni_char;
122    CGGlyph glyph;
123    CTFontRef ct_font = m_font;
124    const CFIndex count = 1;
125    CGRect bounding_rect, success_rect;
126    CGContextRef context_ref;
127
128    if( chnum == ' ' )
129    {
130        uni_char = 'n';
131        CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
132        success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
133        uni_char = chnum;
134        CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
135    }
136    else
137    {
138        uni_char = chnum;
139        CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
140        success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
141    }
142
143    if( CGRectEqualToRect( success_rect, CGRectNull ) == false )
144    {
145        size_t bitmap_width;
146        size_t bitmap_height;
147
148        bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH);
149        bitmap_width = bitmap_width == 0 ? 1 : bitmap_width;
150
151        bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT);
152
153        xoffs = yoffs = 0;
154        width = bitmap_width;
155
156        size_t bits_per_component;
157        CGColorSpaceRef color_space;
158        CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
159
160        color_space = CGColorSpaceCreateDeviceRGB();
161        bits_per_component = 8;
162
163        bitmap.allocate(bitmap_width, bitmap_height);
164
165        context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info );
166
167        if( context_ref != NULL )
168        {
169            CGFontRef font_ref;
170            font_ref = CTFontCopyGraphicsFont( ct_font, NULL );
171            CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) );
172            CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0);
173            CGContextSetFont( context_ref, font_ref );
174            CGContextSetFontSize( context_ref, POINT_SIZE );
175            CGContextShowGlyphs( context_ref, &glyph, count );
176            CGFontRelease( font_ref );
177            CGContextRelease( context_ref );
178        }
179
180        CGColorSpaceRelease( color_space );
181    }
182
183    return bitmap.valid();
184}
185
trunk/src/osd/modules/font/font_unix.c
r0r243011
1/*
2 * font_sdl.c
3 *
4 */
5
6#if (SDLMAME_SDL2)
7#include <SDL2/SDL_ttf.h>
8#else
9#include <SDL/SDL_ttf.h>
10#endif
11#ifndef SDLMAME_HAIKU
12#include <fontconfig/fontconfig.h>
13#endif
14
15#include "osdepend.h"
16
17#include "astring.h"
18#include "corealloc.h"
19#include "fileio.h"
20
21#define POINT_SIZE 144.0
22
23//-------------------------------------------------
24//  font_open - attempt to "open" a handle to the
25//  font with the given name
26//-------------------------------------------------
27
28class osd_font_unix : public osd_font
29{
30public:
31    virtual ~osd_font_unix() {};
32
33    virtual bool open(const char *font_path, const char *name, int &height);
34    virtual void close();
35    virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
36private:
37#ifndef SDLMAME_HAIKU
38    TTF_Font *search_font_config(astring name, bool bold, bool italic, bool underline, bool &bakedstyles);
39#endif
40    bool BDF_Check_Magic(astring name);
41    TTF_Font * TTF_OpenFont_Magic(astring name, int fsize);
42    TTF_Font *m_font;
43};
44
45osd_font *osd_font_alloc()
46{
47    return global_alloc(osd_font_unix);
48}
49
50bool osd_font_unix::open(const char *font_path, const char *_name, int &height)
51{
52    TTF_Font *font = (TTF_Font *)NULL;
53    bool bakedstyles = false;
54    int style = 0;
55
56    // accept qualifiers from the name
57    astring name(_name);
58
59    if (name == "default")
60    {
61        name = "Liberation Sans";
62    }
63
64    bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
65    bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
66    bool underline = (name.replace(0, "[U]", "") + name.replace(0, "[u]", "") > 0);
67    bool strike = (name.replace(0, "[S]", "") + name.replace(0, "[s]", "") > 0);
68
69    // first up, try it as a filename
70    font = TTF_OpenFont_Magic(name, POINT_SIZE);
71
72    // if no success, try the font path
73
74    if (!font)
75    {
76        osd_printf_verbose("Searching font %s in -%s\n", name.cstr(), OPTION_FONTPATH);
77        //emu_file file(options().font_path(), OPEN_FLAG_READ);
78        emu_file file(font_path, OPEN_FLAG_READ);
79        if (file.open(name) == FILERR_NONE)
80        {
81            astring full_name = file.fullpath();
82            font = TTF_OpenFont_Magic(full_name, POINT_SIZE);
83            if (font)
84                osd_printf_verbose("Found font %s\n", full_name.cstr());
85        }
86    }
87
88    // if that didn't work, crank up the FontConfig database
89#ifndef SDLMAME_HAIKU
90    if (!font)
91    {
92        font = search_font_config(name, bold, italic, underline, bakedstyles);
93    }
94#endif
95
96    if (!font)
97    {
98        if (!BDF_Check_Magic(name))
99        {
100            osd_printf_verbose("font %s is not TrueType or BDF, using MAME default\n", name.cstr());
101        }
102        return NULL;
103    }
104
105    // apply styles
106    if (!bakedstyles)
107    {
108        style |= bold ? TTF_STYLE_BOLD : 0;
109        style |= italic ? TTF_STYLE_ITALIC : 0;
110    }
111    style |= underline ? TTF_STYLE_UNDERLINE : 0;
112    // SDL_ttf 2.0.9 and earlier does not define TTF_STYLE_STRIKETHROUGH
113#if SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) > SDL_VERSIONNUM(2,0,9)
114    style |= strike ? TTF_STYLE_STRIKETHROUGH : 0;
115#else
116    if (strike)
117        osd_printf_warning("Ignoring strikethrough for SDL_TTF older than 2.0.10\n");
118#endif // PATCHLEVEL
119    TTF_SetFontStyle(font, style);
120
121    height = TTF_FontLineSkip(font);
122
123    m_font = font;
124    return true;
125}
126
127//-------------------------------------------------
128//  font_close - release resources associated with
129//  a given OSD font
130//-------------------------------------------------
131
132void osd_font_unix::close()
133{
134    TTF_CloseFont(this->m_font);
135}
136
137//-------------------------------------------------
138//  font_get_bitmap - allocate and populate a
139//  BITMAP_FORMAT_ARGB32 bitmap containing the
140//  pixel values rgb_t(0xff,0xff,0xff,0xff)
141//  or rgb_t(0x00,0xff,0xff,0xff) for each
142//  pixel of a black & white font
143//-------------------------------------------------
144
145bool osd_font_unix::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
146{
147    TTF_Font *ttffont;
148    SDL_Surface *drawsurf;
149    SDL_Color fcol = { 0xff, 0xff, 0xff };
150    UINT16 ustr[16];
151
152    ttffont = m_font;
153
154    memset(ustr,0,sizeof(ustr));
155    ustr[0] = (UINT16)chnum;
156    drawsurf = TTF_RenderUNICODE_Solid(ttffont, ustr, fcol);
157
158    // was nothing returned?
159    if (drawsurf)
160    {
161        // allocate a MAME destination bitmap
162        bitmap.allocate(drawsurf->w, drawsurf->h);
163
164        // copy the rendered character image into it
165        for (int y = 0; y < bitmap.height(); y++)
166        {
167            UINT32 *dstrow = &bitmap.pix32(y);
168            UINT8 *srcrow = (UINT8 *)drawsurf->pixels;
169
170            srcrow += (y * drawsurf->pitch);
171
172            for (int x = 0; x < drawsurf->w; x++)
173            {
174                dstrow[x] = srcrow[x] ? rgb_t(0xff,0xff,0xff,0xff) : rgb_t(0x00,0xff,0xff,0xff);
175            }
176        }
177
178        // what are these?
179        xoffs = yoffs = 0;
180        width = drawsurf->w;
181
182        SDL_FreeSurface(drawsurf);
183    }
184
185    return bitmap.valid();
186}
187
188TTF_Font * osd_font_unix::TTF_OpenFont_Magic(astring name, int fsize)
189{
190    emu_file file(OPEN_FLAG_READ);
191    if (file.open(name) == FILERR_NONE)
192    {
193        unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff };
194        unsigned char magic[5] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
195        file.read(buffer,5);
196        if (memcmp(buffer, magic, 5))
197            return NULL;
198    }
199    return TTF_OpenFont(name.cstr(), POINT_SIZE);
200}
201
202bool osd_font_unix::BDF_Check_Magic(astring name)
203{
204    emu_file file(OPEN_FLAG_READ);
205    if (file.open(name) == FILERR_NONE)
206    {
207        unsigned char buffer[9];
208        unsigned char magic[9] = { 'S', 'T', 'A', 'R', 'T', 'F', 'O', 'N', 'T' };
209        file.read(buffer, 9);
210        file.close();
211        if (!memcmp(buffer, magic, 9))
212            return true;
213    }
214
215    return false;
216}
217
218#ifndef SDLMAME_HAIKU
219TTF_Font *osd_font_unix::search_font_config(astring name, bool bold, bool italic, bool underline, bool &bakedstyles)
220{
221    TTF_Font *font = (TTF_Font *)NULL;
222    FcConfig *config;
223    FcPattern *pat;
224    FcObjectSet *os;
225    FcFontSet *fontset;
226    FcValue val;
227
228    config = FcConfigGetCurrent();
229    pat = FcPatternCreate();
230    os = FcObjectSetCreate();
231    FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.cstr());
232
233    // try and get a font with the requested styles baked-in
234    if (bold)
235    {
236        if (italic)
237        {
238            FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold Italic");
239        }
240        else
241        {
242            FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold");
243        }
244    }
245    else if (italic)
246    {
247        FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Italic");
248    }
249    else
250    {
251        FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
252    }
253
254    FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
255
256    FcObjectSetAdd(os, FC_FILE);
257    fontset = FcFontList(config, pat, os);
258
259    for (int i = 0; i < fontset->nfont; i++)
260    {
261        if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
262        {
263            continue;
264        }
265
266        if (val.type != FcTypeString)
267        {
268            continue;
269        }
270
271        osd_printf_verbose("Matching font: %s\n", val.u.s);
272        {
273            astring match_name((const char*)val.u.s);
274            font = TTF_OpenFont_Magic(match_name, POINT_SIZE);
275        }
276
277        if (font)
278        {
279            bakedstyles = true;
280            break;
281        }
282    }
283
284    // didn't get a font above?  try again with no baked-in styles
285    if (!font)
286    {
287        FcPatternDestroy(pat);
288        FcFontSetDestroy(fontset);
289
290        pat = FcPatternCreate();
291        FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.cstr());
292        FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
293        FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
294        fontset = FcFontList(config, pat, os);
295
296        for (int i = 0; i < fontset->nfont; i++)
297        {
298            if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
299            {
300                continue;
301            }
302
303            if (val.type != FcTypeString)
304            {
305                continue;
306            }
307
308            osd_printf_verbose("Matching unstyled font: %s\n", val.u.s);
309            {
310                astring match_name((const char*)val.u.s);
311                font = TTF_OpenFont_Magic(match_name, POINT_SIZE);
312            }
313
314            if (font)
315            {
316                break;
317            }
318        }
319    }
320
321    FcPatternDestroy(pat);
322    FcObjectSetDestroy(os);
323    FcFontSetDestroy(fontset);
324    return font;
325}
326#endif
trunk/src/osd/modules/font/font_windows.c
r0r243011
1/*
2 * font_sdl.c
3 *
4 */
5
6#define WIN32_LEAN_AND_MEAN
7#include <windows.h>
8#include <commctrl.h>
9#include <mmsystem.h>
10#include <tchar.h>
11#include <io.h>
12
13#include "osdepend.h"
14
15#include "strconv.h"
16#include "astring.h"
17#include "corealloc.h"
18#include "fileio.h"
19
20//#define POINT_SIZE 144.0
21#define DEFAULT_FONT_HEIGHT (200)
22
23#if 0
24//============================================================
25//  wstring_from_utf8
26//============================================================
27
28// FIXME: defined in multiple locations ... FIXME
29
30WCHAR *wstring_from_utf8(const char *utf8string)
31{
32    int char_count;
33    WCHAR *result;
34
35    // convert MAME string (UTF-8) to UTF-16
36    char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0);
37    result = (WCHAR *)osd_malloc_array(char_count * sizeof(*result));
38    if (result != NULL)
39        MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);
40
41    return result;
42}
43
44
45//============================================================
46//  utf8_from_wstring
47//============================================================
48
49char *utf8_from_wstring(const WCHAR *wstring)
50{
51    int char_count;
52    char *result;
53
54    // convert UTF-16 to MAME string (UTF-8)
55    char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL);
56    result = (char *)osd_malloc_array(char_count * sizeof(*result));
57    if (result != NULL)
58        WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL);
59
60    return result;
61}
62#endif
63
64//-------------------------------------------------
65//  font_open - attempt to "open" a handle to the
66//  font with the given name
67//-------------------------------------------------
68
69class osd_font_windows : public osd_font
70{
71public:
72    virtual ~osd_font_windows() {};
73
74    virtual bool open(const char *font_path, const char *name, int &height);
75    virtual void close();
76    virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
77private:
78    HGDIOBJ m_font;
79};
80
81osd_font *osd_font_alloc()
82{
83    return global_alloc(osd_font_windows);
84}
85
86bool osd_font_windows::open(const char *font_path, const char *_name, int &height)
87{
88    // accept qualifiers from the name
89    astring name(_name);
90    if (name == "default") name = "Tahoma";
91    bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
92    bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
93
94    // build a basic LOGFONT description of what we want
95    LOGFONT logfont;
96    logfont.lfHeight = DEFAULT_FONT_HEIGHT;
97    logfont.lfWidth = 0;
98    logfont.lfEscapement = 0;
99    logfont.lfOrientation = 0;
100    logfont.lfWeight = bold ? FW_BOLD : FW_MEDIUM;
101    logfont.lfItalic = italic;
102    logfont.lfUnderline = FALSE;
103    logfont.lfStrikeOut = FALSE;
104    logfont.lfCharSet = ANSI_CHARSET;
105    logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
106    logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
107    logfont.lfQuality = NONANTIALIASED_QUALITY;
108    logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
109
110    // copy in the face name
111    TCHAR *face = tstring_from_utf8(name);
112    _tcsncpy(logfont.lfFaceName, face, sizeof(logfont.lfFaceName) / sizeof(TCHAR));
113    logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR)-1] = 0;
114    osd_free(face);
115
116    // create the font
117    height = logfont.lfHeight;
118    m_font = CreateFontIndirect(&logfont);
119    if (m_font == NULL)
120        return false;
121
122    // select it into a temp DC and get the real font name
123    HDC dummyDC = CreateCompatibleDC(NULL);
124    HGDIOBJ oldfont = SelectObject(dummyDC, m_font);
125    TCHAR realname[100];
126    GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname);
127    SelectObject(dummyDC, oldfont);
128    DeleteDC(dummyDC);
129
130    // if it doesn't match our request, fail
131    char *utf = utf8_from_tstring(realname);
132    int result = core_stricmp(utf, name);
133    osd_free(utf);
134
135    // if we didn't match, nuke our font and fall back
136    if (result != 0)
137    {
138        DeleteObject(m_font);
139        m_font = NULL;
140        return false;
141    }
142    return true;
143}
144
145//-------------------------------------------------
146//  font_close - release resources associated with
147//  a given OSD font
148//-------------------------------------------------
149
150void osd_font_windows::close()
151{
152    // delete the font ojbect
153    if (m_font != NULL)
154        DeleteObject(m_font);
155
156}
157
158//-------------------------------------------------
159//  font_get_bitmap - allocate and populate a
160//  BITMAP_FORMAT_ARGB32 bitmap containing the
161//  pixel values rgb_t(0xff,0xff,0xff,0xff)
162//  or rgb_t(0x00,0xff,0xff,0xff) for each
163//  pixel of a black & white font
164//-------------------------------------------------
165
166bool osd_font_windows::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
167{
168    // create a dummy DC to work with
169    HDC dummyDC = CreateCompatibleDC(NULL);
170    HGDIOBJ oldfont = SelectObject(dummyDC, m_font);
171
172    // get the text metrics
173    TEXTMETRIC metrics = { 0 };
174    GetTextMetrics(dummyDC, &metrics);
175
176    // get the width of this character
177    ABC abc;
178    if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
179    {
180        abc.abcA = 0;
181        abc.abcC = 0;
182        GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
183    }
184    width = abc.abcA + abc.abcB + abc.abcC;
185
186    // determine desired bitmap size
187    int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
188    int bmheight = 50 + metrics.tmHeight + 50;
189
190    // describe the bitmap we want
191    BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER)+2 * sizeof(RGBQUAD)] = { 0 };
192    BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
193    info.bmiHeader.biSize = sizeof(info.bmiHeader);
194    info.bmiHeader.biWidth = bmwidth;
195    info.bmiHeader.biHeight = -bmheight;
196    info.bmiHeader.biPlanes = 1;
197    info.bmiHeader.biBitCount = 1;
198    info.bmiHeader.biCompression = BI_RGB;
199    info.bmiHeader.biSizeImage = 0;
200    info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
201    info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
202    info.bmiHeader.biClrUsed = 0;
203    info.bmiHeader.biClrImportant = 0;
204    RGBQUAD col1 = info.bmiColors[0];
205    RGBQUAD col2 = info.bmiColors[1];
206    col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
207    col2.rgbBlue = col2.rgbGreen = col2.rgbRed = 0xff;
208
209    // create a DIB to render to
210    BYTE *bits;
211    HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);
212    HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);
213
214    // clear the bitmap
215    int rowbytes = bmwidth / 8;
216    memset(bits, 0, rowbytes * bmheight);
217
218    // now draw the character
219    WCHAR tempchar = chnum;
220    SetTextColor(dummyDC, RGB(0xff, 0xff, 0xff));
221    SetBkColor(dummyDC, RGB(0x00, 0x00, 0x00));
222    ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);
223
224    // characters are expected to be full-height
225    rectangle actbounds;
226    actbounds.min_y = 50;
227    actbounds.max_y = 50 + metrics.tmHeight - 1;
228
229    // determine the actual left of the character
230    for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
231    {
232        BYTE *offs = bits + actbounds.min_x;
233        UINT8 summary = 0;
234        for (int y = 0; y < bmheight; y++)
235            summary |= offs[y * rowbytes];
236        if (summary != 0)
237        {
238            actbounds.min_x *= 8;
239            if (!(summary & 0x80)) actbounds.min_x++;
240            if (!(summary & 0xc0)) actbounds.min_x++;
241            if (!(summary & 0xe0)) actbounds.min_x++;
242            if (!(summary & 0xf0)) actbounds.min_x++;
243            if (!(summary & 0xf8)) actbounds.min_x++;
244            if (!(summary & 0xfc)) actbounds.min_x++;
245            if (!(summary & 0xfe)) actbounds.min_x++;
246            break;
247        }
248    }
249
250    // determine the actual right of the character
251    for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
252    {
253        BYTE *offs = bits + actbounds.max_x;
254        UINT8 summary = 0;
255        for (int y = 0; y < bmheight; y++)
256            summary |= offs[y * rowbytes];
257        if (summary != 0)
258        {
259            actbounds.max_x *= 8;
260            if (summary & 0x7f) actbounds.max_x++;
261            if (summary & 0x3f) actbounds.max_x++;
262            if (summary & 0x1f) actbounds.max_x++;
263            if (summary & 0x0f) actbounds.max_x++;
264            if (summary & 0x07) actbounds.max_x++;
265            if (summary & 0x03) actbounds.max_x++;
266            if (summary & 0x01) actbounds.max_x++;
267            break;
268        }
269    }
270
271    // allocate a new bitmap
272    if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
273    {
274        bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
275
276        // copy the bits into it
277        for (int y = 0; y < bitmap.height(); y++)
278        {
279            UINT32 *dstrow = &bitmap.pix32(y);
280            UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
281            for (int x = 0; x < bitmap.width(); x++)
282            {
283                int effx = x + actbounds.min_x;
284                dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(0x00, 0xff, 0xff, 0xff);
285            }
286        }
287
288        // set the final offset values
289        xoffs = actbounds.min_x - (50 + abc.abcA);
290        yoffs = actbounds.max_y - (50 + metrics.tmAscent);
291    }
292
293    // de-select the font and release the DC
294    SelectObject(dummyDC, oldbitmap);
295    DeleteObject(dib);
296    SelectObject(dummyDC, oldfont);
297    DeleteDC(dummyDC);
298    return bitmap.valid();
299}
300
trunk/src/osd/osdepend.h
r243010r243011
2626//  TYPE DEFINITIONS
2727//============================================================
2828
29// FIXME: We can do better than this
30class osd_font;
29// ======================> osd_font interface
3130
31class osd_font
32{
33public:
34    virtual ~osd_font() {}
35
36    virtual bool open(const char *font_path, const char *name, int &height) = 0;
37    virtual void close() = 0;
38    virtual bool get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) = 0;
39};
40
3241// ======================> osd_interface
3342
43/* FIXME: this should be replaced by a proper module implementation
44 * For the time being only one font provider can be linked
45 */
46
47osd_font *osd_font_alloc();
48
3449// description of the currently-running machine
3550class osd_interface
3651{
r243010r243011
5267   // input overridables
5368   virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) = 0;
5469
55   // font overridables
56   virtual osd_font *font_open(const char *name, int &height) = 0;
57   virtual void font_close(osd_font *font) = 0;
58   virtual bool font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs) = 0;
59
6070   // video overridables
6171   virtual void *get_slider_list() = 0; // FIXME: returns slider_state *
6272
73   // font interface
74
75   // font is allocated with global_alloc; therefore use global_free!
76   osd_font *font_alloc() { return osd_font_alloc(); }
77
6378   // command option overrides
6479   virtual bool execute_command(const char *command) = 0;
6580
trunk/src/osd/sdl/osdsdl.h
r243010r243011
186186   // input overridables
187187   virtual void customize_input_type_list(simple_list<input_type_entry> &typelist);
188188
189   // font overridables
190   virtual osd_font *font_open(const char *name, int &height);
191   virtual void font_close(osd_font *font);
192   virtual bool font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
193
194189   virtual void video_register();
195190   virtual void sound_register();
196191   virtual void debugger_register();
trunk/src/osd/sdl/sdl.mak
r243010r243011
204204ifeq ($(TARGETOS),unix)
205205BASE_TARGETOS = unix
206206SYNC_IMPLEMENTATION = tc
207FONT_IMPLEMENTATION = unix
207208endif
208209
209210ifeq ($(TARGETOS),linux)
210211BASE_TARGETOS = unix
211212SYNC_IMPLEMENTATION = tc
212213SDL_NETWORK = taptun
214FONT_IMPLEMENTATION = unix
213215
214216ifndef NO_USE_MIDI
215217INCPATH += `pkg-config --cflags alsa`
r243010r243011
221223ifeq ($(TARGETOS),freebsd)
222224BASE_TARGETOS = unix
223225SYNC_IMPLEMENTATION = tc
226FONT_IMPLEMENTATION = unix
224227DEFS += -DNO_AFFINITY_NP
225228LIBS += -lutil
226229# /usr/local/include is not considered a system include directory
r243010r243011
232235ifeq ($(TARGETOS),openbsd)
233236BASE_TARGETOS = unix
234237SYNC_IMPLEMENTATION = ntc
238FONT_IMPLEMENTATION = unix
235239LIBS += -lutil
236240NO_USE_MIDI = 1
237241endif
r243010r243011
239243ifeq ($(TARGETOS),netbsd)
240244BASE_TARGETOS = unix
241245SYNC_IMPLEMENTATION = ntc
246FONT_IMPLEMENTATION = unix
242247LIBS += -lutil
243248NO_USE_MIDI = 1
244249endif
r243010r243011
247252BASE_TARGETOS = unix
248253DEFS += -DNO_AFFINITY_NP -UHAVE_VSNPRINTF -DNO_vsnprintf
249254SYNC_IMPLEMENTATION = tc
255FONT_IMPLEMENTATION = unix
250256NO_USE_MIDI = 1
251257endif
252258
253259ifeq ($(TARGETOS),haiku)
254260BASE_TARGETOS = unix
255261SYNC_IMPLEMENTATION = ntc
262FONT_IMPLEMENTATION = unix
256263NO_X11 = 1
257264NO_USE_XINPUT = 1
258265NO_USE_MIDI = 1
r243010r243011
263270ifeq ($(TARGETOS),emscripten)
264271BASE_TARGETOS = unix
265272SYNC_IMPLEMENTATION = mini
273FONT_IMPLEMENTATION = none
266274NO_DEBUGGER = 1
267275NO_X11 = 1
268276NO_USE_XINPUT = 1
r243010r243011
274282ifeq ($(TARGETOS),macosx)
275283NO_USE_QTDEBUG = 1
276284BASE_TARGETOS = unix
285FONT_IMPLEMENTATION = osx
277286DEFS += -DSDLMAME_UNIX -DSDLMAME_MACOSX -DSDLMAME_DARWIN
278287
279288ifndef NO_USE_MIDI
r243010r243011
326335ifeq ($(TARGETOS),win32)
327336BASE_TARGETOS = win32
328337SYNC_IMPLEMENTATION = windows
338FONT_IMPLEMENTATION = windows
329339NO_X11 = 1
330340NO_USE_XINPUT = 1
331341DEFS += -DSDLMAME_WIN32 -DX64_WINDOWS_ABI
r243010r243011
363373BASE_TARGETOS = os2
364374DEFS += -DSDLMAME_OS2
365375SYNC_IMPLEMENTATION = os2
376FONT_IMPLEMENTATION = none
366377NO_DEBUGGER = 1
367378NO_X11 = 1
368379NO_USE_XINPUT = 1
r243010r243011
387398endif
388399endif
389400
401ifndef FONT_IMPLEMENTATION
402$(error Please define FONT_IMPLEMENTATION !)
403endif
404
405
390406#-------------------------------------------------
391407# object and source roots
392408#-------------------------------------------------
r243010r243011
398414   $(OSDOBJ)/modules/sync \
399415   $(OSDOBJ)/modules/lib \
400416   $(OSDOBJ)/modules/midi \
417   $(OSDOBJ)/modules/font \
401418
402419#-------------------------------------------------
403420# OSD core library
r243010r243011
412429   $(SDLOBJ)/sdlmisc_$(BASE_TARGETOS).o    \
413430   $(SDLOBJ)/sdlos_$(SDLOS_TARGETOS).o \
414431   $(OSDOBJ)/modules/lib/osdlib_$(SDLOS_TARGETOS).o \
415   $(OSDOBJ)/modules/sync/sync_$(SYNC_IMPLEMENTATION).o
432   $(OSDOBJ)/modules/sync/sync_$(SYNC_IMPLEMENTATION).o \
433   $(OSDOBJ)/modules/font/font_$(FONT_IMPLEMENTATION).o  \
416434
417435ifdef NOASM
418436OSDCOREOBJS += $(OSDOBJ)/modules/sync/work_mini.o
trunk/src/osd/sdl/sdlmain.c
r243010r243011
8585
8686#include "watchdog.h"
8787
88#define DEFAULT_FONT_HEIGHT (200)
89
9088//============================================================
9189//  OPTIONS
9290//============================================================
r243010r243011
303301   setvbuf(stdout, (char *) NULL, _IONBF, 0);
304302   setvbuf(stderr, (char *) NULL, _IONBF, 0);
305303
304   //FIXME: move to font module
306305   #ifdef SDLMAME_UNIX
307306   sdl_entered_debugger = 0;
308307   #if (!defined(SDLMAME_MACOSX)) && (!defined(SDLMAME_HAIKU)) && (!defined(SDLMAME_EMSCRIPTEN))
r243010r243011
712711#endif
713712}
714713
715#if defined(SDLMAME_UNIX) && (!defined(SDLMAME_EMSCRIPTEN))
716#define POINT_SIZE 144.0
717
718#ifdef SDLMAME_MACOSX
719
720#define EXTRA_HEIGHT 1.0
721#define EXTRA_WIDTH 1.15
722
723//-------------------------------------------------
724//  font_open - attempt to "open" a handle to the
725//  font with the given name
726//-------------------------------------------------
727
728class osd_font
729{
730public:
731    CTFontRef m_font;
732};
733
734osd_font *sdl_osd_interface::font_open(const char *_name, int &height)
735{
736   CFStringRef font_name = NULL;
737   CTFontRef ct_font = NULL;
738   CTFontDescriptorRef font_descriptor;
739   CGAffineTransform affine_transform = CGAffineTransformIdentity;
740
741   astring name(_name);
742
743   if (name == "default")
744   {
745      name = "LucidaGrande";
746   }
747
748   /* handle bdf fonts in the core */
749   if (name.len() > 4)
750      if (name.makeupper().substr(name.len()-4,4) == ".BDF" )
751         return NULL;
752
753   font_name = CFStringCreateWithCString( NULL, name.cstr(), kCFStringEncodingUTF8 );
754
755   if( font_name != NULL )
756   {
757      font_descriptor = CTFontDescriptorCreateWithNameAndSize( font_name, POINT_SIZE );
758
759      if( font_descriptor != NULL )
760      {
761         ct_font = CTFontCreateWithFontDescriptor( font_descriptor, POINT_SIZE, &affine_transform );
762
763         CFRelease( font_descriptor );
764      }
765   }
766
767   CFRelease( font_name );
768
769   if (!ct_font)
770   {
771      osd_printf_verbose("Couldn't find/open font %s, using MAME default\n", name.cstr());
772      return NULL;
773   }
774
775   CFStringRef real_name = CTFontCopyPostScriptName( ct_font );
776   char real_name_c_string[255];
777   CFStringGetCString ( real_name, real_name_c_string, 255, kCFStringEncodingUTF8 );
778   osd_printf_verbose("Matching font: %s\n", real_name_c_string);
779   CFRelease( real_name );
780
781   CGFloat line_height = 0.0;
782   line_height += CTFontGetAscent(ct_font);
783   line_height += CTFontGetDescent(ct_font);
784   line_height += CTFontGetLeading(ct_font);
785   height = ceilf(line_height * EXTRA_HEIGHT);
786
787   osd_font *ret = global_alloc(osd_font);
788   ret->m_font = ct_font;
789   return ret;
790}
791
792//-------------------------------------------------
793//  font_close - release resources associated with
794//  a given OSD font
795//-------------------------------------------------
796
797void sdl_osd_interface::font_close(osd_font *font)
798{
799   CTFontRef ct_font = font->m_font;
800
801   if( ct_font != NULL )
802   {
803      CFRelease( ct_font );
804   }
805   global_free(font);
806}
807
808//-------------------------------------------------
809//  font_get_bitmap - allocate and populate a
810//  BITMAP_FORMAT_ARGB32 bitmap containing the
811//  pixel values rgb_t(0xff,0xff,0xff,0xff)
812//  or rgb_t(0x00,0xff,0xff,0xff) for each
813//  pixel of a black & white font
814//-------------------------------------------------
815
816bool sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
817{
818   UniChar uni_char;
819   CGGlyph glyph;
820   CTFontRef ct_font = font->m_font;
821   const CFIndex count = 1;
822   CGRect bounding_rect, success_rect;
823   CGContextRef context_ref;
824
825   if( chnum == ' ' )
826   {
827      uni_char = 'n';
828      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
829      success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
830      uni_char = chnum;
831      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
832   }
833   else
834   {
835      uni_char = chnum;
836      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
837      success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
838   }
839
840   if( CGRectEqualToRect( success_rect, CGRectNull ) == false )
841   {
842      size_t bitmap_width;
843      size_t bitmap_height;
844
845      bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH);
846      bitmap_width = bitmap_width == 0 ? 1 : bitmap_width;
847
848      bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT);
849
850      xoffs = yoffs = 0;
851      width = bitmap_width;
852
853      size_t bits_per_component;
854      CGColorSpaceRef color_space;
855      CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
856
857      color_space = CGColorSpaceCreateDeviceRGB();
858      bits_per_component = 8;
859
860      bitmap.allocate(bitmap_width, bitmap_height);
861
862      context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info );
863
864      if( context_ref != NULL )
865      {
866         CGFontRef font_ref;
867         font_ref = CTFontCopyGraphicsFont( ct_font, NULL );
868         CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) );
869         CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0);
870         CGContextSetFont( context_ref, font_ref );
871         CGContextSetFontSize( context_ref, POINT_SIZE );
872         CGContextShowGlyphs( context_ref, &glyph, count );
873         CGFontRelease( font_ref );
874         CGContextRelease( context_ref );
875      }
876
877      CGColorSpaceRelease( color_space );
878   }
879
880   return bitmap.valid();
881}
882#else // UNIX but not OSX
883
884static TTF_Font * TTF_OpenFont_Magic(astring name, int fsize)
885{
886   emu_file file(OPEN_FLAG_READ);
887   if (file.open(name) == FILERR_NONE)
888   {
889      unsigned char buffer[5] = { 0xff, 0xff, 0xff, 0xff, 0xff };
890      unsigned char magic[5] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
891      file.read(buffer,5);
892      if (memcmp(buffer, magic, 5))
893         return NULL;
894   }
895   return TTF_OpenFont(name.cstr(), POINT_SIZE);
896}
897
898static bool BDF_Check_Magic(astring name)
899{
900   emu_file file(OPEN_FLAG_READ);
901   if (file.open(name) == FILERR_NONE)
902   {
903      unsigned char buffer[9];
904      unsigned char magic[9] = { 'S', 'T', 'A', 'R', 'T', 'F', 'O', 'N', 'T' };
905      file.read(buffer, 9);
906      file.close();
907      if (!memcmp(buffer, magic, 9))
908         return true;
909   }
910
911   return false;
912}
913
914#ifndef SDLMAME_HAIKU
915static TTF_Font *search_font_config(astring name, bool bold, bool italic, bool underline, bool &bakedstyles)
916{
917   TTF_Font *font = (TTF_Font *)NULL;
918   FcConfig *config;
919   FcPattern *pat;
920   FcObjectSet *os;
921   FcFontSet *fontset;
922   FcValue val;
923
924   config = FcConfigGetCurrent();
925   pat = FcPatternCreate();
926   os = FcObjectSetCreate();
927   FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.cstr());
928
929   // try and get a font with the requested styles baked-in
930   if (bold)
931   {
932      if (italic)
933      {
934         FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold Italic");
935      }
936      else
937      {
938         FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Bold");
939      }
940   }
941   else if (italic)
942   {
943      FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Italic");
944   }
945   else
946   {
947      FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
948   }
949
950   FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
951
952   FcObjectSetAdd(os, FC_FILE);
953   fontset = FcFontList(config, pat, os);
954
955   for (int i = 0; i < fontset->nfont; i++)
956   {
957      if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
958      {
959         continue;
960      }
961
962      if (val.type != FcTypeString)
963      {
964         continue;
965      }
966
967      osd_printf_verbose("Matching font: %s\n", val.u.s);
968      {
969         astring match_name((const char*)val.u.s);
970         font = TTF_OpenFont_Magic(match_name, POINT_SIZE);
971      }
972
973      if (font)
974      {
975         bakedstyles = true;
976         break;
977      }
978   }
979
980   // didn't get a font above?  try again with no baked-in styles
981   if (!font)
982   {
983      FcPatternDestroy(pat);
984      FcFontSetDestroy(fontset);
985
986      pat = FcPatternCreate();
987      FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *)name.cstr());
988      FcPatternAddString(pat, FC_STYLE, (const FcChar8 *)"Regular");
989      FcPatternAddString(pat, FC_FONTFORMAT, (const FcChar8 *)"TrueType");
990      fontset = FcFontList(config, pat, os);
991
992      for (int i = 0; i < fontset->nfont; i++)
993      {
994         if (FcPatternGet(fontset->fonts[i], FC_FILE, 0, &val) != FcResultMatch)
995         {
996            continue;
997         }
998
999         if (val.type != FcTypeString)
1000         {
1001            continue;
1002         }
1003
1004         osd_printf_verbose("Matching unstyled font: %s\n", val.u.s);
1005         {
1006            astring match_name((const char*)val.u.s);
1007            font = TTF_OpenFont_Magic(match_name, POINT_SIZE);
1008         }
1009
1010         if (font)
1011         {
1012            break;
1013         }
1014      }
1015   }
1016
1017   FcPatternDestroy(pat);
1018   FcObjectSetDestroy(os);
1019   FcFontSetDestroy(fontset);
1020   return font;
1021}
1022#endif
1023
1024//-------------------------------------------------
1025//  font_open - attempt to "open" a handle to the
1026//  font with the given name
1027//-------------------------------------------------
1028
1029class osd_font
1030{
1031public:
1032    TTF_Font *m_font;
1033};
1034
1035osd_font *sdl_osd_interface::font_open(const char *_name, int &height)
1036{
1037   TTF_Font *font = (TTF_Font *)NULL;
1038   bool bakedstyles = false;
1039   int style = 0;
1040
1041   // accept qualifiers from the name
1042   astring name(_name);
1043
1044   if (name == "default")
1045   {
1046      name = "Liberation Sans";
1047   }
1048
1049   bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
1050   bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
1051   bool underline = (name.replace(0, "[U]", "") + name.replace(0, "[u]", "") > 0);
1052   bool strike = (name.replace(0, "[S]", "") + name.replace(0, "[s]", "") > 0);
1053
1054   // first up, try it as a filename
1055   font = TTF_OpenFont_Magic(name, POINT_SIZE);
1056
1057   // if no success, try the font path
1058
1059   if (!font)
1060   {
1061      osd_printf_verbose("Searching font %s in -%s\n", name.cstr(), OPTION_FONTPATH);
1062      emu_file file(options().font_path(), OPEN_FLAG_READ);
1063      if (file.open(name) == FILERR_NONE)
1064      {
1065         astring full_name = file.fullpath();
1066         font = TTF_OpenFont_Magic(full_name, POINT_SIZE);
1067         if (font)
1068            osd_printf_verbose("Found font %s\n", full_name.cstr());
1069      }
1070   }
1071
1072   // if that didn't work, crank up the FontConfig database
1073#ifndef SDLMAME_HAIKU
1074   if (!font)
1075   {
1076      font = search_font_config(name, bold, italic, underline, bakedstyles);
1077   }
1078#endif
1079
1080   if (!font)
1081   {
1082      if (!BDF_Check_Magic(name))
1083      {
1084         osd_printf_verbose("font %s is not TrueType or BDF, using MAME default\n", name.cstr());
1085      }
1086      return NULL;
1087   }
1088
1089   // apply styles
1090   if (!bakedstyles)
1091   {
1092      style |= bold ? TTF_STYLE_BOLD : 0;
1093      style |= italic ? TTF_STYLE_ITALIC : 0;
1094   }
1095   style |= underline ? TTF_STYLE_UNDERLINE : 0;
1096   // SDL_ttf 2.0.9 and earlier does not define TTF_STYLE_STRIKETHROUGH
1097#if SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) > SDL_VERSIONNUM(2,0,9)
1098   style |= strike ? TTF_STYLE_STRIKETHROUGH : 0;
1099#else
1100   if (strike)
1101      osd_printf_warning("Ignoring strikethrough for SDL_TTF older than 2.0.10\n");
1102#endif // PATCHLEVEL
1103   TTF_SetFontStyle(font, style);
1104
1105   height = TTF_FontLineSkip(font);
1106
1107   osd_font *ret = global_alloc(osd_font);
1108   ret->m_font = font;
1109   return ret;
1110}
1111
1112//-------------------------------------------------
1113//  font_close - release resources associated with
1114//  a given OSD font
1115//-------------------------------------------------
1116
1117void sdl_osd_interface::font_close(osd_font *font)
1118{
1119   TTF_CloseFont(font->m_font);
1120   global_free(font);
1121}
1122
1123//-------------------------------------------------
1124//  font_get_bitmap - allocate and populate a
1125//  BITMAP_FORMAT_ARGB32 bitmap containing the
1126//  pixel values rgb_t(0xff,0xff,0xff,0xff)
1127//  or rgb_t(0x00,0xff,0xff,0xff) for each
1128//  pixel of a black & white font
1129//-------------------------------------------------
1130
1131bool sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
1132{
1133   TTF_Font *ttffont;
1134   SDL_Surface *drawsurf;
1135   SDL_Color fcol = { 0xff, 0xff, 0xff };
1136   UINT16 ustr[16];
1137
1138   ttffont = font->m_font;
1139
1140   memset(ustr,0,sizeof(ustr));
1141   ustr[0] = (UINT16)chnum;
1142   drawsurf = TTF_RenderUNICODE_Solid(ttffont, ustr, fcol);
1143
1144   // was nothing returned?
1145   if (drawsurf)
1146   {
1147      // allocate a MAME destination bitmap
1148      bitmap.allocate(drawsurf->w, drawsurf->h);
1149
1150      // copy the rendered character image into it
1151      for (int y = 0; y < bitmap.height(); y++)
1152      {
1153         UINT32 *dstrow = &bitmap.pix32(y);
1154         UINT8 *srcrow = (UINT8 *)drawsurf->pixels;
1155
1156         srcrow += (y * drawsurf->pitch);
1157
1158         for (int x = 0; x < drawsurf->w; x++)
1159         {
1160            dstrow[x] = srcrow[x] ? rgb_t(0xff,0xff,0xff,0xff) : rgb_t(0x00,0xff,0xff,0xff);
1161         }
1162      }
1163
1164      // what are these?
1165      xoffs = yoffs = 0;
1166      width = drawsurf->w;
1167
1168      SDL_FreeSurface(drawsurf);
1169   }
1170
1171   return bitmap.valid();
1172}
1173#endif  // not OSX
1174#else   // not UNIX
1175714#ifdef SDLMAME_WIN32
1176715
1177716//============================================================
r243010r243011
1211750   return result;
1212751}
1213752
1214osd_font *sdl_osd_interface::font_open(const char *_name, int &height)
1215{
1216   // accept qualifiers from the name
1217   astring name(_name);
1218   if (name == "default") name = "Tahoma";
1219   bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
1220   bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
1221
1222   // build a basic LOGFONT description of what we want
1223   LOGFONT logfont;
1224   logfont.lfHeight = DEFAULT_FONT_HEIGHT;
1225   logfont.lfWidth = 0;
1226   logfont.lfEscapement = 0;
1227   logfont.lfOrientation = 0;
1228   logfont.lfWeight = bold ? FW_BOLD : FW_MEDIUM;
1229   logfont.lfItalic = italic;
1230   logfont.lfUnderline = FALSE;
1231   logfont.lfStrikeOut = FALSE;
1232   logfont.lfCharSet = ANSI_CHARSET;
1233   logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
1234   logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1235   logfont.lfQuality = NONANTIALIASED_QUALITY;
1236   logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1237
1238   // copy in the face name
1239   TCHAR *face = tstring_from_utf8(name);
1240   _tcsncpy(logfont.lfFaceName, face, sizeof(logfont.lfFaceName) / sizeof(TCHAR));
1241   logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR)-1] = 0;
1242   osd_free(face);
1243
1244   // create the font
1245   height = logfont.lfHeight;
1246   osd_font *font = reinterpret_cast<osd_font *>(CreateFontIndirect(&logfont));
1247   if (font == NULL)
1248      return NULL;
1249
1250   // select it into a temp DC and get the real font name
1251   HDC dummyDC = CreateCompatibleDC(NULL);
1252   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
1253   TCHAR realname[100];
1254   GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname);
1255   SelectObject(dummyDC, oldfont);
1256   DeleteDC(dummyDC);
1257
1258   // if it doesn't match our request, fail
1259   char *utf = utf8_from_tstring(realname);
1260   int result = core_stricmp(utf, name);
1261   osd_free(utf);
1262
1263   // if we didn't match, nuke our font and fall back
1264   if (result != 0)
1265   {
1266      DeleteObject(reinterpret_cast<HFONT>(font));
1267      font = NULL;
1268   }
1269   return font;
1270}
1271
1272
1273//-------------------------------------------------
1274//  font_close - release resources associated with
1275//  a given OSD font
1276//-------------------------------------------------
1277
1278void sdl_osd_interface::font_close(osd_font *font)
1279{
1280   // delete the font ojbect
1281   if (font != NULL)
1282      DeleteObject(reinterpret_cast<HFONT>(font));
1283}
1284
1285
1286//-------------------------------------------------
1287//  font_get_bitmap - allocate and populate a
1288//  BITMAP_FORMAT_ARGB32 bitmap containing the
1289//  pixel values rgb_t(0xff,0xff,0xff,0xff)
1290//  or rgb_t(0x00,0xff,0xff,0xff) for each
1291//  pixel of a black & white font
1292//-------------------------------------------------
1293
1294bool sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
1295{
1296   // create a dummy DC to work with
1297   HDC dummyDC = CreateCompatibleDC(NULL);
1298   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
1299
1300   // get the text metrics
1301   TEXTMETRIC metrics = { 0 };
1302   GetTextMetrics(dummyDC, &metrics);
1303
1304   // get the width of this character
1305   ABC abc;
1306   if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
1307   {
1308      abc.abcA = 0;
1309      abc.abcC = 0;
1310      GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
1311   }
1312   width = abc.abcA + abc.abcB + abc.abcC;
1313
1314   // determine desired bitmap size
1315   int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
1316   int bmheight = 50 + metrics.tmHeight + 50;
1317
1318   // describe the bitmap we want
1319   BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER)+2 * sizeof(RGBQUAD)] = { 0 };
1320   BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
1321   info.bmiHeader.biSize = sizeof(info.bmiHeader);
1322   info.bmiHeader.biWidth = bmwidth;
1323   info.bmiHeader.biHeight = -bmheight;
1324   info.bmiHeader.biPlanes = 1;
1325   info.bmiHeader.biBitCount = 1;
1326   info.bmiHeader.biCompression = BI_RGB;
1327   info.bmiHeader.biSizeImage = 0;
1328   info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
1329   info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
1330   info.bmiHeader.biClrUsed = 0;
1331   info.bmiHeader.biClrImportant = 0;
1332   RGBQUAD col1 = info.bmiColors[0];
1333   RGBQUAD col2 = info.bmiColors[1];
1334   col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
1335   col2.rgbBlue = col2.rgbGreen = col2.rgbRed = 0xff;
1336
1337   // create a DIB to render to
1338   BYTE *bits;
1339   HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);
1340   HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);
1341
1342   // clear the bitmap
1343   int rowbytes = bmwidth / 8;
1344   memset(bits, 0, rowbytes * bmheight);
1345
1346   // now draw the character
1347   WCHAR tempchar = chnum;
1348   SetTextColor(dummyDC, RGB(0xff, 0xff, 0xff));
1349   SetBkColor(dummyDC, RGB(0x00, 0x00, 0x00));
1350   ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);
1351
1352   // characters are expected to be full-height
1353   rectangle actbounds;
1354   actbounds.min_y = 50;
1355   actbounds.max_y = 50 + metrics.tmHeight - 1;
1356
1357   // determine the actual left of the character
1358   for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
1359   {
1360      BYTE *offs = bits + actbounds.min_x;
1361      UINT8 summary = 0;
1362      for (int y = 0; y < bmheight; y++)
1363         summary |= offs[y * rowbytes];
1364      if (summary != 0)
1365      {
1366         actbounds.min_x *= 8;
1367         if (!(summary & 0x80)) actbounds.min_x++;
1368         if (!(summary & 0xc0)) actbounds.min_x++;
1369         if (!(summary & 0xe0)) actbounds.min_x++;
1370         if (!(summary & 0xf0)) actbounds.min_x++;
1371         if (!(summary & 0xf8)) actbounds.min_x++;
1372         if (!(summary & 0xfc)) actbounds.min_x++;
1373         if (!(summary & 0xfe)) actbounds.min_x++;
1374         break;
1375      }
1376   }
1377
1378   // determine the actual right of the character
1379   for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
1380   {
1381      BYTE *offs = bits + actbounds.max_x;
1382      UINT8 summary = 0;
1383      for (int y = 0; y < bmheight; y++)
1384         summary |= offs[y * rowbytes];
1385      if (summary != 0)
1386      {
1387         actbounds.max_x *= 8;
1388         if (summary & 0x7f) actbounds.max_x++;
1389         if (summary & 0x3f) actbounds.max_x++;
1390         if (summary & 0x1f) actbounds.max_x++;
1391         if (summary & 0x0f) actbounds.max_x++;
1392         if (summary & 0x07) actbounds.max_x++;
1393         if (summary & 0x03) actbounds.max_x++;
1394         if (summary & 0x01) actbounds.max_x++;
1395         break;
1396      }
1397   }
1398
1399   // allocate a new bitmap
1400   if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
1401   {
1402      bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
1403
1404      // copy the bits into it
1405      for (int y = 0; y < bitmap.height(); y++)
1406      {
1407         UINT32 *dstrow = &bitmap.pix32(y);
1408         UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
1409         for (int x = 0; x < bitmap.width(); x++)
1410         {
1411            int effx = x + actbounds.min_x;
1412            dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(0x00, 0xff, 0xff, 0xff);
1413         }
1414      }
1415
1416      // set the final offset values
1417      xoffs = actbounds.min_x - (50 + abc.abcA);
1418      yoffs = actbounds.max_y - (50 + metrics.tmAscent);
1419   }
1420
1421   // de-select the font and release the DC
1422   SelectObject(dummyDC, oldbitmap);
1423   DeleteObject(dib);
1424   SelectObject(dummyDC, oldfont);
1425   DeleteDC(dummyDC);
1426   return bitmap.valid();
1427}
1428
1429#else
1430
1431//-------------------------------------------------
1432//  font_open - attempt to "open" a handle to the
1433//  font with the given name
1434//-------------------------------------------------
1435
1436osd_font *sdl_osd_interface::font_open(const char *_name, int &height)
1437{
1438   return (osd_font *)NULL;
1439}
1440
1441//-------------------------------------------------
1442//  font_close - release resources associated with
1443//  a given OSD font
1444//-------------------------------------------------
1445
1446void sdl_osd_interface::font_close(osd_font *font)
1447{
1448}
1449
1450//-------------------------------------------------
1451//  font_get_bitmap - allocate and populate a
1452//  BITMAP_FORMAT_ARGB32 bitmap containing the
1453//  pixel values rgb_t(0xff,0xff,0xff,0xff)
1454//  or rgb_t(0x00,0xff,0xff,0xff) for each
1455//  pixel of a black & white font
1456//-------------------------------------------------
1457
1458bool sdl_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
1459{
1460   return false;
1461}
1462753#endif
1463#endif
1464754
1465755
trunk/src/osd/windows/windows.mak
r243010r243011
9191   $(OSDOBJ)/modules/sync \
9292   $(OSDOBJ)/modules/lib \
9393   $(OSDOBJ)/modules/midi \
94   $(OSDOBJ)/modules/font \
9495
9596ifdef USE_QTDEBUG
9697OBJDIRS += $(OSDOBJ)/modules/debugger/qt
r243010r243011
356357   $(WINOBJ)/winsocket.o \
357358   $(OSDOBJ)/modules/sync/work_osd.o \
358359   $(OSDOBJ)/modules/lib/osdlib_win32.o \
360   $(OSDOBJ)/modules/font/font_windows.o \
359361   $(WINOBJ)/winptty.o \
360362
361363
trunk/src/osd/windows/winmain.c
r243010r243011
713713   winwindow_process_events(machine(), 0, 0);
714714}
715715
716
717//-------------------------------------------------
718//  font_open - attempt to "open" a handle to the
719//  font with the given name
720//-------------------------------------------------
721
722osd_font *windows_osd_interface::font_open(const char *_name, int &height)
723{
724   // accept qualifiers from the name
725   astring name(_name);
726   if (name == "default") name = "Tahoma";
727   bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
728   bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
729
730   // build a basic LOGFONT description of what we want
731   LOGFONT logfont;
732   logfont.lfHeight = DEFAULT_FONT_HEIGHT;
733   logfont.lfWidth = 0;
734   logfont.lfEscapement = 0;
735   logfont.lfOrientation = 0;
736   logfont.lfWeight = bold ? FW_BOLD : FW_MEDIUM;
737   logfont.lfItalic = italic;
738   logfont.lfUnderline = FALSE;
739   logfont.lfStrikeOut = FALSE;
740   logfont.lfCharSet = ANSI_CHARSET;
741   logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
742   logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
743   logfont.lfQuality = NONANTIALIASED_QUALITY;
744   logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
745
746   // copy in the face name
747   TCHAR *face = tstring_from_utf8(name);
748   _tcsncpy(logfont.lfFaceName, face, sizeof(logfont.lfFaceName) / sizeof(TCHAR));
749   logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR) - 1] = 0;
750   osd_free(face);
751
752   // create the font
753   height = logfont.lfHeight;
754   osd_font *font = reinterpret_cast<osd_font *>(CreateFontIndirect(&logfont));
755   if (font == NULL)
756      return NULL;
757
758   // select it into a temp DC and get the real font name
759   HDC dummyDC = CreateCompatibleDC(NULL);
760   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
761   TCHAR realname[100];
762   GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname);
763   SelectObject(dummyDC, oldfont);
764   DeleteDC(dummyDC);
765
766   // if it doesn't match our request, fail
767   char *utf = utf8_from_tstring(realname);
768   int result = core_stricmp(utf, name);
769   osd_free(utf);
770
771   // if we didn't match, nuke our font and fall back
772   if (result != 0)
773   {
774      DeleteObject(reinterpret_cast<HFONT>(font));
775      font = NULL;
776   }
777   return font;
778}
779
780
781//-------------------------------------------------
782//  font_close - release resources associated with
783//  a given OSD font
784//-------------------------------------------------
785
786void windows_osd_interface::font_close(osd_font *font)
787{
788   // delete the font ojbect
789   if (font != NULL)
790      DeleteObject(reinterpret_cast<HFONT>(font));
791}
792
793
794//-------------------------------------------------
795//  font_get_bitmap - allocate and populate a
796//  BITMAP_FORMAT_ARGB32 bitmap containing the
797//  pixel values rgb_t(0xff,0xff,0xff,0xff)
798//  or rgb_t(0x00,0xff,0xff,0xff) for each
799//  pixel of a black & white font
800//-------------------------------------------------
801
802bool windows_osd_interface::font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
803{
804   // create a dummy DC to work with
805   HDC dummyDC = CreateCompatibleDC(NULL);
806   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
807
808   // get the text metrics
809   TEXTMETRIC metrics = { 0 };
810   GetTextMetrics(dummyDC, &metrics);
811
812   // get the width of this character
813   ABC abc;
814   if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
815   {
816      abc.abcA = 0;
817      abc.abcC = 0;
818      GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
819   }
820   width = abc.abcA + abc.abcB + abc.abcC;
821
822   // determine desired bitmap size
823   int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
824   int bmheight = 50 + metrics.tmHeight + 50;
825
826   // describe the bitmap we want
827   BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)] = { 0 };
828   BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
829   info.bmiHeader.biSize = sizeof(info.bmiHeader);
830   info.bmiHeader.biWidth = bmwidth;
831   info.bmiHeader.biHeight = -bmheight;
832   info.bmiHeader.biPlanes = 1;
833   info.bmiHeader.biBitCount = 1;
834   info.bmiHeader.biCompression = BI_RGB;
835   info.bmiHeader.biSizeImage = 0;
836   info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
837   info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
838   info.bmiHeader.biClrUsed = 0;
839   info.bmiHeader.biClrImportant = 0;
840   RGBQUAD col1 = info.bmiColors[0];
841   RGBQUAD col2 = info.bmiColors[1];
842   col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
843   col2.rgbBlue = col2.rgbGreen = col2.rgbRed = 0xff;
844
845   // create a DIB to render to
846   BYTE *bits;
847   HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);
848   HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);
849
850   // clear the bitmap
851   int rowbytes = bmwidth / 8;
852   memset(bits, 0, rowbytes * bmheight);
853
854   // now draw the character
855   WCHAR tempchar = chnum;
856   SetTextColor(dummyDC, RGB(0xff,0xff,0xff));
857   SetBkColor(dummyDC, RGB(0x00,0x00,0x00));
858   ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);
859
860   // characters are expected to be full-height
861   rectangle actbounds;
862   actbounds.min_y = 50;
863   actbounds.max_y = 50 + metrics.tmHeight - 1;
864
865   // determine the actual left of the character
866   for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
867   {
868      BYTE *offs = bits + actbounds.min_x;
869      UINT8 summary = 0;
870      for (int y = 0; y < bmheight; y++)
871         summary |= offs[y * rowbytes];
872      if (summary != 0)
873      {
874         actbounds.min_x *= 8;
875         if (!(summary & 0x80)) actbounds.min_x++;
876         if (!(summary & 0xc0)) actbounds.min_x++;
877         if (!(summary & 0xe0)) actbounds.min_x++;
878         if (!(summary & 0xf0)) actbounds.min_x++;
879         if (!(summary & 0xf8)) actbounds.min_x++;
880         if (!(summary & 0xfc)) actbounds.min_x++;
881         if (!(summary & 0xfe)) actbounds.min_x++;
882         break;
883      }
884   }
885
886   // determine the actual right of the character
887   for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
888   {
889      BYTE *offs = bits + actbounds.max_x;
890      UINT8 summary = 0;
891      for (int y = 0; y < bmheight; y++)
892         summary |= offs[y * rowbytes];
893      if (summary != 0)
894      {
895         actbounds.max_x *= 8;
896         if (summary & 0x7f) actbounds.max_x++;
897         if (summary & 0x3f) actbounds.max_x++;
898         if (summary & 0x1f) actbounds.max_x++;
899         if (summary & 0x0f) actbounds.max_x++;
900         if (summary & 0x07) actbounds.max_x++;
901         if (summary & 0x03) actbounds.max_x++;
902         if (summary & 0x01) actbounds.max_x++;
903         break;
904      }
905   }
906
907   // allocate a new bitmap
908   if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
909   {
910      bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
911
912      // copy the bits into it
913      for (int y = 0; y < bitmap.height(); y++)
914      {
915         UINT32 *dstrow = &bitmap.pix32(y);
916         UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
917         for (int x = 0; x < bitmap.width(); x++)
918         {
919            int effx = x + actbounds.min_x;
920            dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? rgb_t(0xff,0xff,0xff,0xff) : rgb_t(0x00,0xff,0xff,0xff);
921         }
922      }
923
924      // set the final offset values
925      xoffs = actbounds.min_x - (50 + abc.abcA);
926      yoffs = actbounds.max_y - (50 + metrics.tmAscent);
927   }
928
929   // de-select the font and release the DC
930   SelectObject(dummyDC, oldbitmap);
931   DeleteObject(dib);
932   SelectObject(dummyDC, oldfont);
933   DeleteDC(dummyDC);
934   return bitmap.valid();
935}
936
937
938716//============================================================
939717//  winmain_dump_stack
940718//============================================================
trunk/src/osd/windows/winmain.h
r243010r243011
252252   // input overridables
253253   virtual void customize_input_type_list(simple_list<input_type_entry> &typelist);
254254
255   // font overridables
256   virtual osd_font *font_open(const char *name, int &height);
257   virtual void font_close(osd_font *font);
258   virtual bool font_get_bitmap(osd_font *font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs);
259
260255   virtual void video_register();
261256   virtual void sound_register();
262257   virtual void debugger_register();


Previous 199869 Revisions Next


© 1997-2024 The MAME Team