Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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
}
Пример #4
0
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;
}