В соответствии с «лучшими практиками», которые я изучил, мы должны загружать ресурсы, необходимые для наших программ, в оперативную память, избегая ненужных запросов на жесткий диск пользователя. Используя SDL2, я всегда освобождаю файлы изображений после загрузки их в оперативную память. (Файл -> Поверхность -> Текстура -> Свободный файл / Поверхность). Поэтому, если я изменяю файл другим приложением, моя программа игнорирует его, поскольку файл больше не используется им.
Теперь в уроке 16 я учусь пользоваться дополнением SDL_ttf
.
Однако, используя SDL_ttf
addon, я не смог найти способ освободить файл font.ttf
и загрузить его в оперативную память. Я могу видеть это только через указатель. Мне кажется, что файл продолжает читаться каждый раз, когда я отрисовываю текст.
Как я могу загрузить его в ОЗУ, чтобы рендеринг вызывал позицию ОЗУ вместо файла в HD?
Полный код
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
int G = 255;
int main (void) {SDL_SetMainReady();
int SCREEN_WIDTH = 800;
int SCREEN_HEIGHT = 600;
bool QUIT_APPLICATION = false;
SDL_Event union_Event_manager;
SDL_Color str_White_colour = {255,255,255,255};
SDL_Window * ptr_Window = nullptr;
SDL_Surface * ptr_Text_Surface = nullptr;
SDL_Surface * ptr_Main_surface = nullptr;
SDL_RWops * ptr_str_rwops = nullptr;
TTF_Font * ptr_Font = nullptr;
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
ptr_Window = SDL_CreateWindow("Lesson 16 - TrueTypeFonts", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
ptr_Main_surface = SDL_GetWindowSurface(ptr_Window);
ptr_str_rwops = SDL_RWFromFile("FreeMono.ttf", "r");
ptr_Font = TTF_OpenFontIndexRW(ptr_str_rwops, 1, 72, 0);
ptr_Text_Surface = TTF_RenderText_Solid(ptr_Font, "Hello World", str_White_colour);
while(!QUIT_APPLICATION){
while(SDL_PollEvent(&union_Event_manager) != 0 ){
if (union_Event_manager.type == SDL_QUIT) {QUIT_APPLICATION = true;}
/*END WHILE*/}
SDL_BlitSurface(ptr_Text_Surface, NULL, ptr_Main_surface, NULL);
SDL_UpdateWindowSurface(ptr_Window);
/*END WHILE*/}
TTF_CloseFont(ptr_Font);
// if called before any rendering, the app crashes, as supposed to.
// So, how free the **file** and keep using its content from RAM?
SDL_RWclose(ptr_str_rwops);
SDL_FreeSurface(ptr_Text_Surface);
SDL_FreeSurface(ptr_Main_surface);
SDL_DestroyWindow(ptr_Window);
ptr_Font = nullptr;
ptr_str_rwops = nullptr;
ptr_Text_Surface = nullptr;
ptr_Main_surface = nullptr;
ptr_Window = nullptr;
TTF_Quit();
SDL_Quit();
return (0);}
Ошибка 1:
Создать структуру для хранения информации из файла.
TTF_Font str_Font; // Error in compilation ''incomplete type''
str_Font = *ptr_Font;
TTF_CloseFont(ptr_Font);
ptr_Font = nullptr;
ptr_Font = &str_Font;
Причина отказа:
Я неправильно понял, как работает файл. Структура содержит только информацию о файле, но не сам носитель.
Этот подход бесполезен и приводит к аварийному завершению работы программы сразу после освобождения указателя (рендеринг пытается разыменовать nullptr
).
Ошибка 2:
Используйте встроенную функцию для освобождения ресурса.
ptr_Font = TTF_OpenFontIndexRW(SDL_RWFromFile("FreeMono.ttf", "r"), 1, 72, 0);
Причина отказа:
Я не понимаю, почему, поскольку второй аргумент (ненулевой) указывает, что он должен освободить ресурс после использования. Это также происходит в приведенном выше исходном коде, где я просто разделил функции на две строки.
Ошибка 3:
Создать структуру для хранения информации об указателе.
ptr_str_rwops = SDL_RWFromFile("FreeMono.ttf", "r");
str_rwops = *ptr_str_rwops;
SDL_RWclose(ptr_str_rwops); // crashes the program
ptr_str_rwops = nullptr;
ptr_str_rwops = &str_rwops; // useless: file still in use.
Причина отказа:
Структура RWops, похоже, не содержит файл, а только информацию о нем. Так что это сумма ошибок 1 и 2.
Ошибка 4:
Пытался загрузить файл как объект.
ptr_LoadObject = (TTF_Font*)SDL_LoadObject("FreeMono.ttf");
ptr_str_rwops = SDL_RWFromFile((const char *)ptr_LoadObject, "r");
Причина отказа:
Эта функция работает с общими файлами операционной системы. Неправильное использование функции.
Обновление 2019-04-05
Отказ 5
Пытался сделать копию файла прямо в ОЗУ, используя memcpy
long int func_discover_file_size(char* file){
long int var_file_size = 0;
FILE * ptr_file = nullptr;
ptr_file = fopen(file, "rb");
fseek(ptr_file , 0L , SEEK_END);
var_file_size = ftell(ptr_file);
fclose(ptr_file);
return var_file_size;
/*END func_discover_file_size*/}
int main (void) {
/*cut unrelated code*/
void * ptr_load_file = nullptr;
void * ptr_File_copy = nullptr;
long int var_file_size = 0;
/*cut unrelated code*/
var_file_size = func_discover_file_size("FreeMono.ttf");
// works fine and returns correct size of file.
ptr_File_copy = (char*) calloc (1, var_file_size);
// memory allocation works fine (tested)
ptr_load_file = fopen("FreeMono.ttf", "rb");
// file loaded correctly. Test with FOR LOOP shows content of file in console.
memcpy(ptr_File_copy, ptr_load_file, var_file_size);
// program crashes in line above
Причина отказа:
Похоже, я не знаю, как правильно использовать memcpy. Я перепробовал множество приведений для работы и указателей (void, char), попытался изменить тип указателей на char, void, FILE, попытался вывести на третий указатель ...
Теперь я ищу хорошую душу, чтобы осветить мои пути ...: -p
примечание: C помечен, потому что SDL