static VALUE Font_initialize(VALUE self, VALUE rbRealFilePath, VALUE rbSize, VALUE rbBold, VALUE rbItalic, VALUE rbTtcIndex) { const char* path = StringValueCStr(rbRealFilePath); const int size = NUM2INT(rbSize); const bool bold = RTEST(rbBold); const bool italic = RTEST(rbItalic); const int ttcIndex = NUM2INT(rbTtcIndex); Font* font; Data_Get_Struct(self, Font, font); font->size = size; font->sdlFont = TTF_OpenFontIndex(path, size, ttcIndex); if (!font->sdlFont) { rb_raise(strb_GetStarRubyErrorClass(), "%s (%s)", TTF_GetError(), path); } const int style = TTF_STYLE_NORMAL | (bold ? TTF_STYLE_BOLD : 0) | (italic ? TTF_STYLE_ITALIC : 0); TTF_SetFontStyle(font->sdlFont, style); return Qnil; }
static void SearchFont(VALUE rbFilePathOrName, VALUE* volatile rbRealFilePath, int* ttcIndex) { *rbRealFilePath = Qnil; if (ttcIndex != NULL) { *ttcIndex = -1; } *rbRealFilePath = strb_GetCompletePath(rbFilePathOrName, false); if (!NIL_P(*rbRealFilePath)) { return; } volatile VALUE rbFontNameSymbol = ID2SYM(rb_intern_str(rbFilePathOrName)); FontFileInfo* info = fontFileInfos; while (info) { if (info->rbFontNameSymbol == rbFontNameSymbol) { *rbRealFilePath = rb_str_new2(rb_id2name(SYM2ID(info->rbFileNameSymbol))); #ifdef WIN32 volatile VALUE rbTemp = rb_str_new2(rb_id2name(SYM2ID(rbWindowsFontDirPathSymbol))); *rbRealFilePath = rb_str_concat(rb_str_cat2(rbTemp, "\\"), *rbRealFilePath); #endif if (ttcIndex != NULL) { *ttcIndex = info->ttcIndex; } return; } info = info->next; } #ifdef HAVE_FONTCONFIG_FONTCONFIG_H if (!FcInit()) { FcFini(); rb_raise(strb_GetStarRubyErrorClass(), "can't initialize fontconfig library"); return; } int nameLength = RSTRING_LEN(rbFilePathOrName) + 1; char name[nameLength]; strncpy(name, StringValueCStr(rbFilePathOrName), nameLength); char* delimiter = strchr(name, ','); char* style = NULL; if (delimiter) { *delimiter = '\0'; style = delimiter + 1; char* nameTail = delimiter - 1; while (*nameTail == ' ') { *nameTail = '\0'; nameTail--; } while (*style == ' ') { style++; } } FcPattern* pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, name, NULL); if (style && 0 < strlen(style)) { FcPatternAddString(pattern, FC_STYLE, (FcChar8*)style); } FcObjectSet* objectSet = FcObjectSetBuild(FC_FAMILY, FC_FILE, NULL); FcFontSet* fontSet = FcFontList(NULL, pattern, objectSet); if (objectSet) { FcObjectSetDestroy(objectSet); } if (pattern) { FcPatternDestroy(pattern); } if (fontSet) { for (int i = 0; i < fontSet->nfont; i++) { FcChar8* fileName = NULL; if (FcPatternGetString(fontSet->fonts[i], FC_FILE, 0, &fileName) == FcResultMatch) { FcChar8* fontName = FcNameUnparse(fontSet->fonts[i]); *rbRealFilePath = rb_str_new2((char*)fileName); volatile VALUE rbFontName = rb_str_new2((char*)fontName); free(fontName); fontName = NULL; if (ttcIndex != NULL && strchr(StringValueCStr(rbFontName), ',')) { *ttcIndex = 0; } } } FcFontSetDestroy(fontSet); } FcFini(); if (!NIL_P(*rbRealFilePath)) { return; } #endif return; }
void strb_InitializeSdlFont(void) { if (TTF_Init()) { rb_raise_sdl_ttf_error(); } fontFileInfos = ALLOC(FontFileInfo); fontFileInfos->rbFontNameSymbol = Qundef; fontFileInfos->rbFileNameSymbol = Qundef; fontFileInfos->ttcIndex = -1; fontFileInfos->next = NULL; FontFileInfo* currentInfo = fontFileInfos; (void)currentInfo; #ifdef WIN32 HKEY hKey; TCHAR* regPath = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"); if (SUCCEEDED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, KEY_READ, &hKey))) { DWORD fontNameBuffMaxLength; DWORD fileNameBuffMaxByteLength; RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &fontNameBuffMaxLength, &fileNameBuffMaxByteLength, NULL, NULL); TCHAR fontNameBuff[fontNameBuffMaxLength + 1]; BYTE fileNameByteBuff[fileNameBuffMaxByteLength]; for (DWORD dwIndex = 0; ;dwIndex++) { ZeroMemory(fontNameBuff, sizeof(fontNameBuff)); ZeroMemory(fileNameByteBuff, sizeof(fileNameByteBuff)); DWORD fontNameBuffLength = sizeof(fontNameBuff) / sizeof(TCHAR); DWORD fileNameBuffByteLength = fileNameBuffMaxByteLength; LONG result = RegEnumValue(hKey, dwIndex, fontNameBuff, &fontNameBuffLength, NULL, NULL, fileNameByteBuff, &fileNameBuffByteLength); TCHAR* fileNameBuff = (TCHAR*)fileNameByteBuff; DWORD fileNameBuffLength = _tcslen(fileNameBuff); if (result == ERROR_SUCCESS) { const TCHAR* ext = &(fileNameBuff[fileNameBuffLength - 3]); if (tolower(ext[0]) == _T('t') && tolower(ext[1]) == _T('t') && (tolower(ext[2]) == _T('f') || tolower(ext[2]) == _T('c'))) { TCHAR* fontName = fontNameBuff; const TCHAR* fileName = fileNameBuff; // A TTF font name must end with ' (TrueType)'. fontName[fontNameBuffLength - 11] = _T('\0'); for (int i = fileNameBuffLength - 1; 0 <= i; i--) { if (fileName[i] == _T('\\')) { fileName += i + 1; break; } } int length = WideCharToMultiByte(CP_UTF8, 0, fontName, -1, NULL, 0, NULL, NULL); char fontNameUTF8[length]; WideCharToMultiByte(CP_UTF8, 0, fontName, -1, fontNameUTF8, length, NULL, NULL); volatile VALUE rbFontName = rb_str_new2(fontNameUTF8); length = WideCharToMultiByte(CP_ACP, 0, fileName, -1, NULL, 0, NULL, NULL); char fileNameANSI[length]; WideCharToMultiByte(CP_ACP, 0, fileName, -1, fileNameANSI, length, NULL, NULL); volatile VALUE rbFileName = rb_str_new2(fileNameANSI); if (strchr(StringValueCStr(rbFontName), '&')) { volatile VALUE rbArr = rb_str_split(rbFontName, "&"); const int arrLength = RARRAY_LEN(rbArr); int ttcIndex = 0; for (int i = 0; i < arrLength; i++) { volatile VALUE rbFontName = rb_ary_entry(rbArr, i); rb_funcall(rbFontName, rb_intern("strip!"), 0); if (0 < RSTRING_LEN(rbFontName)) { volatile VALUE rbFontNameSymbol = rb_str_intern(rbFontName); volatile VALUE rbFileNameSymbol = rb_str_intern(rbFileName); ADD_INFO(currentInfo, rbFontNameSymbol, rbFileNameSymbol, ttcIndex); ttcIndex++; } } } else { volatile VALUE rbFontNameSymbol = rb_str_intern(rbFontName); volatile VALUE rbFileNameSymbol = rb_str_intern(rbFileName); ADD_INFO(currentInfo, rbFontNameSymbol, rbFileNameSymbol, -1); } } } else { break; } } RegCloseKey(hKey); } else { rb_raise(strb_GetStarRubyErrorClass(), "Win32API error: %d", (int)GetLastError()); } TCHAR szWindowsFontDirPath[MAX_PATH + 1]; if (FAILED(SHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, szWindowsFontDirPath))) { rb_raise(strb_GetStarRubyErrorClass(), "Win32API error: %d", (int)GetLastError()); } int length = WideCharToMultiByte(CP_UTF8, 0, szWindowsFontDirPath, -1, NULL, 0, NULL, NULL); char szWindowsFontDirPathUTF8[length]; WideCharToMultiByte(CP_UTF8, 0, szWindowsFontDirPath, -1, szWindowsFontDirPathUTF8, length, NULL, NULL); volatile VALUE rbWindowsFontDirPath = rb_str_new2(szWindowsFontDirPathUTF8); rbWindowsFontDirPathSymbol = rb_str_intern(rbWindowsFontDirPath); #endif }
static VALUE Game_initialize(int argc, VALUE* argv, VALUE self) { if (!NIL_P(Game_s_current(rb_cGame))) { rb_raise(strb_GetStarRubyErrorClass(), "already run"); } volatile VALUE rbWidth, rbHeight, rbOptions; rb_scan_args(argc, argv, "21", &rbWidth, &rbHeight, &rbOptions); if (NIL_P(rbOptions)) { rbOptions = rb_hash_new(); } else { Check_Type(rbOptions, T_HASH); } Game* game; Data_Get_Struct(self, Game, game); if (SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER)) { rb_raise_sdl_error(); } const int width = NUM2INT(rbWidth); const int height = NUM2INT(rbHeight); volatile VALUE rbFps = rb_hash_aref(rbOptions, symbol_fps); Game_fps_eq(self, !NIL_P(rbFps) ? rbFps : INT2FIX(30)); volatile VALUE rbTitle = rb_hash_aref(rbOptions, symbol_title); Game_title_eq(self, !NIL_P(rbTitle) ? rbTitle : rb_str_new2("")); bool cursor = false; volatile VALUE val; Check_Type(rbOptions, T_HASH); if (!NIL_P(val = rb_hash_aref(rbOptions, symbol_cursor))) { cursor = RTEST(val); } if (!NIL_P(val = rb_hash_aref(rbOptions, symbol_fullscreen))) { game->isFullscreen = RTEST(val); } if (!NIL_P(val = rb_hash_aref(rbOptions, symbol_window_scale))) { game->windowScale = NUM2INT(val); if (game->windowScale < 1) { rb_raise(rb_eArgError, "invalid window scale: %d", game->windowScale); } } if (!NIL_P(val = rb_hash_aref(rbOptions, symbol_vsync))) { game->isVsync = RTEST(val); } SDL_ShowCursor(cursor ? SDL_ENABLE : SDL_DISABLE); volatile VALUE rbScreen = rb_class_new_instance(2, (VALUE[]){INT2NUM(width), INT2NUM(height)}, strb_GetTextureClass()); game->screen = rbScreen; InitializeScreen(game); rb_iv_set(rb_cGame, "current", self); return Qnil; }