#include "sdl_helpers.h" #include #include #include #include #include using namespace std; using nlohmann::json; map, TTF_Font*> font_map; string default_font_name = "font.ttf"; bool init_sdl() { if (SDL_Init(SDL_INIT_VIDEO) < 0) { cout << "SDL could not initialize! SDL - " << SDL_GetError() << endl; return false; } if (0 != TTF_Init()) { cout << "Could not init TTF! SDL - " << SDL_GetError() << endl; SDL_Quit(); return false; } int img_flags = IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF); if (img_flags != (IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF)) { cout << "Could not init IMG! SDL - " << SDL_GetError() << endl; TTF_Quit(); SDL_Quit(); return false; } return true; } void clean_sdl() { // Clean up all fonts for (auto it = font_map.begin(); it != font_map.end(); ++it) { TTF_CloseFont(it->second); } font_map.clear(); IMG_Quit(); TTF_Quit(); SDL_Quit(); } TTF_Font* get_font(int size, const string& filename) { pair key(filename, size); if (0 != font_map.count(key)) { return font_map[key]; } else { TTF_Font* font = TTF_OpenFont(filename.c_str(), size); if (nullptr != font) { font_map[key] = font; } else { cout << "Could not open font '"<< filename << "' with size " << size << endl; } return font; } } SDL_Rect surface_align(const SDL_Surface* base, const SDL_Surface* applied, HorizontalAlign halign, VerticalAlign valign, const SDL_Rect* hint_external) { SDL_Rect align = {.x = 0, .y = 0, .w = 0, .h = 0}; SDL_Rect hint; if ((nullptr == base) || (nullptr == applied)) { return align; } // These are set in order to handle scaled blits align.w = applied->w; align.h = applied->h; if (nullptr == hint_external) { hint = SDL_Rect{.x = 0, .y = 0, .w = applied->w, .h = applied->h}; } else { hint = *hint_external; } switch (halign) { case HALIGN_LEFT: align.x = -hint.x; break; case HALIGN_CENTER: align.x = base->w / 2 - hint.x - hint.w / 2; break; case HALIGN_RIGHT: align.x = base->w - (hint.x + hint.w); break; } switch (valign) { case VALIGN_TOP: align.y = -hint.y; break; case VALIGN_CENTER: align.y = base->h / 2 - hint.y - hint.h / 2; break; case VALIGN_BOTTOM: align.y = base->h - (hint.y + hint.h); break; } return align; } bool read_config_json(json& cfg, const string& filename, ostream* log) { ifstream cfg_file(filename); if (!cfg_file.is_open()) { if (nullptr != log) { *log << "Could not open config.json" << endl; } return false; } // Parse with comments try { cfg = json::parse(cfg_file, nullptr, true, true); } catch (const std::exception &e) { if (nullptr != log) { *log << e.what() << endl; } return false; } return true; } void json_extract(const json& j, const string& key, string& out) { if (j.contains(key) && j[key].is_string()) { out = j[key]; } } void json_extract(const json& j, const string& key, int& out) { if (j.contains(key) && j[key].is_number_integer()) { out = j[key]; } } void json_extract(const json& j, const string& key, bool& out) { if (j.contains(key) && j[key].is_boolean()) { out = j[key]; } } void json_extract(const json& j, const string& key, HorizontalAlign& out) { if (j.contains(key)) { try { out = j[key].get(); } catch(const std::exception& e) { } } } void json_extract(const json& j, const string& key, VerticalAlign& out) { if (j.contains(key)) { try { out = j[key].get(); } catch(const std::exception& e) { } } } void json_extract(const json& j, const string& key, TextFit& out) { if (j.contains(key)) { try { out = j[key].get(); } catch(const std::exception& e) { } } } void json_extract(const json& j, const string& key, SDL_Color& out) { if (j.contains(key) && j[key].is_object()) { const json& j2 = j[key]; json_extract(j2, "r", out.r); json_extract(j2, "g", out.g); json_extract(j2, "b", out.b); json_extract(j2, "a", out.a); } } void json_extract(const json& j, const string& key, Uint8& out) { if (j.contains(key) && j[key].is_number_unsigned()) { out = j[key]; } } void json_extract(const json& j, const string& key, ImageResize& out) { if (j.contains(key)) { try { out = j[key].get(); } catch(const std::exception& e) { } } }