Previous 199869 Revisions Next

r32114 Sunday 14th September, 2014 at 15:44:26 UTC by R. Belmont
SDL: use Windows OSD's font-selection semantics for SDL Windows builds. [R. Belmont]
[src/osd/sdl]sdlmain.c

trunk/src/osd/sdl/sdlmain.c
r32113r32114
7373
7474#include "watchdog.h"
7575
76#define DEFAULT_FONT_HEIGHT (200)
77
7678//============================================================
7779//  OPTIONS
7880//============================================================
r32113r32114
11411143}
11421144#endif  // not OSX
11431145#else   // not UNIX
1146#ifdef SDLMAME_WIN32
1147
1148//============================================================
1149//  wstring_from_utf8
1150//============================================================
1151
1152WCHAR *wstring_from_utf8(const char *utf8string)
1153{
1154   int char_count;
1155   WCHAR *result;
1156
1157   // convert MAME string (UTF-8) to UTF-16
1158   char_count = MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, NULL, 0);
1159   result = (WCHAR *)osd_malloc_array(char_count * sizeof(*result));
1160   if (result != NULL)
1161      MultiByteToWideChar(CP_UTF8, 0, utf8string, -1, result, char_count);
1162
1163   return result;
1164}
1165
1166
1167//============================================================
1168//  utf8_from_wstring
1169//============================================================
1170
1171char *utf8_from_wstring(const WCHAR *wstring)
1172{
1173   int char_count;
1174   char *result;
1175
1176   // convert UTF-16 to MAME string (UTF-8)
1177   char_count = WideCharToMultiByte(CP_UTF8, 0, wstring, -1, NULL, 0, NULL, NULL);
1178   result = (char *)osd_malloc_array(char_count * sizeof(*result));
1179   if (result != NULL)
1180      WideCharToMultiByte(CP_UTF8, 0, wstring, -1, result, char_count, NULL, NULL);
1181
1182   return result;
1183}
1184
1185osd_font sdl_osd_interface::font_open(const char *_name, int &height)
1186{
1187   // accept qualifiers from the name
1188   astring name(_name);
1189   if (name == "default") name = "Tahoma";
1190   bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0);
1191   bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0);
1192
1193   // build a basic LOGFONT description of what we want
1194   LOGFONT logfont;
1195   logfont.lfHeight = DEFAULT_FONT_HEIGHT;
1196   logfont.lfWidth = 0;
1197   logfont.lfEscapement = 0;
1198   logfont.lfOrientation = 0;
1199   logfont.lfWeight = bold ? FW_BOLD : FW_MEDIUM;
1200   logfont.lfItalic = italic;
1201   logfont.lfUnderline = FALSE;
1202   logfont.lfStrikeOut = FALSE;
1203   logfont.lfCharSet = ANSI_CHARSET;
1204   logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
1205   logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1206   logfont.lfQuality = NONANTIALIASED_QUALITY;
1207   logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1208
1209   // copy in the face name
1210   TCHAR *face = wstring_from_utf8(name);
1211   wcsncpy(logfont.lfFaceName, face, sizeof(logfont.lfFaceName) / sizeof(TCHAR));
1212   logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR)-1] = 0;
1213   osd_free(face);
1214
1215   // create the font
1216   height = logfont.lfHeight;
1217   osd_font font = reinterpret_cast<osd_font>(CreateFontIndirect(&logfont));
1218   if (font == NULL)
1219      return NULL;
1220
1221   // select it into a temp DC and get the real font name
1222   HDC dummyDC = CreateCompatibleDC(NULL);
1223   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
1224   TCHAR realname[100];
1225   GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname);
1226   SelectObject(dummyDC, oldfont);
1227   DeleteDC(dummyDC);
1228
1229   // if it doesn't match our request, fail
1230   char *utf = utf8_from_wstring(realname);
1231   int result = core_stricmp(utf, name);
1232   osd_free(utf);
1233
1234   // if we didn't match, nuke our font and fall back
1235   if (result != 0)
1236   {
1237      DeleteObject(reinterpret_cast<HFONT>(font));
1238      font = NULL;
1239   }
1240   return font;
1241}
1242
1243
11441244//-------------------------------------------------
1245//  font_close - release resources associated with
1246//  a given OSD font
1247//-------------------------------------------------
1248
1249void sdl_osd_interface::font_close(osd_font font)
1250{
1251   // delete the font ojbect
1252   if (font != NULL)
1253      DeleteObject(reinterpret_cast<HFONT>(font));
1254}
1255
1256
1257//-------------------------------------------------
1258//  font_get_bitmap - allocate and populate a
1259//  BITMAP_FORMAT_ARGB32 bitmap containing the
1260//  pixel values rgb_t(0xff,0xff,0xff,0xff)
1261//  or rgb_t(0x00,0xff,0xff,0xff) for each
1262//  pixel of a black & white font
1263//-------------------------------------------------
1264
1265bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
1266{
1267   // create a dummy DC to work with
1268   HDC dummyDC = CreateCompatibleDC(NULL);
1269   HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast<HGDIOBJ>(font));
1270
1271   // get the text metrics
1272   TEXTMETRIC metrics = { 0 };
1273   GetTextMetrics(dummyDC, &metrics);
1274
1275   // get the width of this character
1276   ABC abc;
1277   if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
1278   {
1279      abc.abcA = 0;
1280      abc.abcC = 0;
1281      GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
1282   }
1283   width = abc.abcA + abc.abcB + abc.abcC;
1284
1285   // determine desired bitmap size
1286   int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
1287   int bmheight = 50 + metrics.tmHeight + 50;
1288
1289   // describe the bitmap we want
1290   BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER)+2 * sizeof(RGBQUAD)] = { 0 };
1291   BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
1292   info.bmiHeader.biSize = sizeof(info.bmiHeader);
1293   info.bmiHeader.biWidth = bmwidth;
1294   info.bmiHeader.biHeight = -bmheight;
1295   info.bmiHeader.biPlanes = 1;
1296   info.bmiHeader.biBitCount = 1;
1297   info.bmiHeader.biCompression = BI_RGB;
1298   info.bmiHeader.biSizeImage = 0;
1299   info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
1300   info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
1301   info.bmiHeader.biClrUsed = 0;
1302   info.bmiHeader.biClrImportant = 0;
1303   RGBQUAD col1 = info.bmiColors[0];
1304   RGBQUAD col2 = info.bmiColors[1];
1305   col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
1306   col2.rgbBlue = col2.rgbGreen = col2.rgbRed = 0xff;
1307
1308   // create a DIB to render to
1309   BYTE *bits;
1310   HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);
1311   HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);
1312
1313   // clear the bitmap
1314   int rowbytes = bmwidth / 8;
1315   memset(bits, 0, rowbytes * bmheight);
1316
1317   // now draw the character
1318   WCHAR tempchar = chnum;
1319   SetTextColor(dummyDC, RGB(0xff, 0xff, 0xff));
1320   SetBkColor(dummyDC, RGB(0x00, 0x00, 0x00));
1321   ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);
1322
1323   // characters are expected to be full-height
1324   rectangle actbounds;
1325   actbounds.min_y = 50;
1326   actbounds.max_y = 50 + metrics.tmHeight - 1;
1327
1328   // determine the actual left of the character
1329   for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
1330   {
1331      BYTE *offs = bits + actbounds.min_x;
1332      UINT8 summary = 0;
1333      for (int y = 0; y < bmheight; y++)
1334         summary |= offs[y * rowbytes];
1335      if (summary != 0)
1336      {
1337         actbounds.min_x *= 8;
1338         if (!(summary & 0x80)) actbounds.min_x++;
1339         if (!(summary & 0xc0)) actbounds.min_x++;
1340         if (!(summary & 0xe0)) actbounds.min_x++;
1341         if (!(summary & 0xf0)) actbounds.min_x++;
1342         if (!(summary & 0xf8)) actbounds.min_x++;
1343         if (!(summary & 0xfc)) actbounds.min_x++;
1344         if (!(summary & 0xfe)) actbounds.min_x++;
1345         break;
1346      }
1347   }
1348
1349   // determine the actual right of the character
1350   for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
1351   {
1352      BYTE *offs = bits + actbounds.max_x;
1353      UINT8 summary = 0;
1354      for (int y = 0; y < bmheight; y++)
1355         summary |= offs[y * rowbytes];
1356      if (summary != 0)
1357      {
1358         actbounds.max_x *= 8;
1359         if (summary & 0x7f) actbounds.max_x++;
1360         if (summary & 0x3f) actbounds.max_x++;
1361         if (summary & 0x1f) actbounds.max_x++;
1362         if (summary & 0x0f) actbounds.max_x++;
1363         if (summary & 0x07) actbounds.max_x++;
1364         if (summary & 0x03) actbounds.max_x++;
1365         if (summary & 0x01) actbounds.max_x++;
1366         break;
1367      }
1368   }
1369
1370   // allocate a new bitmap
1371   if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
1372   {
1373      bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);
1374
1375      // copy the bits into it
1376      for (int y = 0; y < bitmap.height(); y++)
1377      {
1378         UINT32 *dstrow = &bitmap.pix32(y);
1379         UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
1380         for (int x = 0; x < bitmap.width(); x++)
1381         {
1382            int effx = x + actbounds.min_x;
1383            dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(0x00, 0xff, 0xff, 0xff);
1384         }
1385      }
1386
1387      // set the final offset values
1388      xoffs = actbounds.min_x - (50 + abc.abcA);
1389      yoffs = actbounds.max_y - (50 + metrics.tmAscent);
1390   }
1391
1392   // de-select the font and release the DC
1393   SelectObject(dummyDC, oldbitmap);
1394   DeleteObject(dib);
1395   SelectObject(dummyDC, oldfont);
1396   DeleteDC(dummyDC);
1397   return bitmap.valid();
1398}
1399
1400#else
1401
1402//-------------------------------------------------
11451403//  font_open - attempt to "open" a handle to the
11461404//  font with the given name
11471405//-------------------------------------------------
r32113r32114
11731431   return false;
11741432}
11751433#endif
1434#endif

Previous 199869 Revisions Next


© 1997-2024 The MAME Team