Получение segfault с использованием SDL2 TTF_RenderText при загрузке шрифта с использованием TTF_OpenRW? - PullRequest
0 голосов
/ 27 мая 2020

Мой проект пытается загрузить шрифт для рендеринга из zip-файла. Я использую LibZip для доступа к zip-архиву, и процедура, которую я использую, отлично работает для всей графики, которую я визуализирую. Однако использование того же процесса для загрузки шрифта ttf в конечном итоге вызывает segfault, когда я пытаюсь визуализировать текст с помощью функций TTF_RenderText SDL_ttf. Я проверил эту причину, заменив код загрузки на TTF_Open и успешно загрузил его, в то время как загрузка из zip с использованием моего кода заканчивается segfault. Вот код, который я использую для загрузки файла из zip-архива:

TTF_Font* m_load_font(const char* filename, int fontsize) {
  zip_stat_t filestat;
  uint64_t filetotal;
  SDL_RWops* rwop = SDL_AllocRW();

  //Check to see if the data stream got allocated
  if ( rwop == NULL ) {
    u_error(std::cerr, CC_ERROR_SDL, "SDL_AllocRW");
    SDL_FreeRW(rwop);
    return nullptr;
  }
  //Check to see if the resource zip is open
  if ( cc_zip_res == NULL ) {
    std::cerr << "Font Load Error: Zip File Not Loaded" << std::endl;
    SDL_FreeRW(rwop);
    return nullptr;
  }
  //Open the file
  zip_file_t* file = zip_fopen(cc_zip_res, filename, 0);
  if (file == NULL) {
    u_error(std::cerr, CC_ERROR_ZIP, "zip_fopen");
    zip_fclose(file);
    SDL_FreeRW(rwop);
    return nullptr;
  }
  //Read the file
  if(zip_stat(cc_zip_res, filename, 0, &filestat) == -1) {
    u_error(std::cerr, CC_ERROR_ZIP, "zip_stat");
    zip_fclose(file);
    SDL_FreeRW(rwop);
    return nullptr;
  }
  //Write data to a data holding array
  char* rwbuffer = new char[filestat.size];
  rwop = SDL_RWFromMem(rwbuffer, filestat.size);
  while(filetotal < filestat.size) {
    char buffer[256];
    int64_t length;
    //read the file into the buffer
    length = zip_fread(file, buffer, 256);
    if (length == -1) {
      u_error(std::cerr, CC_ERROR_ZIP, "zip_fread");
      zip_fclose(file);
      SDL_FreeRW(rwop);
      delete[] rwbuffer;
      return nullptr;
    }
    //write the buffer into the rwop stream
    if ( (size_t)length != SDL_RWwrite(rwop, buffer, 1, (size_t)length) ) {
      u_error(std::cerr, CC_ERROR_SDL, "SDL_RWwrite");
      zip_fclose(file);
      SDL_FreeRW(rwop);
      delete[] rwbuffer;
      return nullptr;
    }
    //Increment the count so that the loop ends
    filetotal += length;
  }
  zip_fclose(file);
  //Return the seek pointer of the RWop to the beginning so that the file can be read
  SDL_RWseek(rwop,0,RW_SEEK_SET);
  //Load the font from the rwop
  TTF_Font* temp = TTF_OpenFontRW(rwop, 0, fontsize);
  SDL_FreeRW(rwop);
  delete[] rwbuffer;
  if (temp == NULL) {
    u_error(std::cerr, CC_ERROR_TTF, "TTF_OpenFontRw");
  }
  return temp;
}

И вот код, который я использую, с TTF_RenderText:

bool CC_Texture::load_from_font(TTF_Font* font, std::string* text, SDL_Color color,
  SDL_Renderer* ren) {
  if (font == NULL) {
    std::cerr << "Font is Null in CC_Texture::load_from_font" << std::endl;
    return false;
  }
  //The wrap length is an estimate, will figure out the exact
  SDL_Surface* surf = TTF_RenderText_Blended_Wrapped(font, text->c_str(), color, 600);
  if (surf == NULL) {
    u_error(std::cerr, CC_ERROR_TTF, "TTF_RenderText_Blended_Wrapped");
    return false;
  }
  texture = std::shared_ptr<SDL_Texture>(SDL_CreateTextureFromSurface(ren, surf),
    SDL_DestroyTexture);
  if (texture.get() == NULL) {
    u_error(std::cerr, CC_ERROR_SDL, "SDL_CreateTextureFromSurface");
    return false;
  }
  return true;
}

EDIT: я также должен сказать, что Я использовал отладчик для сброса содержимого rwbuffer после того, как он загрузил, и это был действительный файл шрифта, поэтому не похоже, что чтение zip является проблемой.

...