266 lines
4.4 KiB
C++
266 lines
4.4 KiB
C++
#include "sdl_helpers.h"
|
|
|
|
#include <SDL2/SDL.h>
|
|
#include <SDL2/SDL_image.h>
|
|
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <utility>
|
|
|
|
using namespace std;
|
|
using nlohmann::json;
|
|
|
|
map<pair<string, int>, 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<string, int> 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<HorizontalAlign>();
|
|
}
|
|
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<VerticalAlign>();
|
|
}
|
|
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<TextFit>();
|
|
}
|
|
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<ImageResize>();
|
|
}
|
|
catch(const std::exception& e)
|
|
{
|
|
}
|
|
}
|
|
}
|