trmnl_sdl/main.cpp

138 lines
2.9 KiB
C++

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "json.hpp"
#include "sdl_helpers.h"
#include "Widgets/Widget.h"
#include "Widgets/WidgetImage.h"
#include "Widgets/WidgetRect.h"
#include "Widgets/WidgetText.h"
using std::cout;
using std::endl;
using std::map;
using std::shared_ptr;
using std::string;
using std::unique_ptr;
using std::vector;
using nlohmann::json;
void init_builders(map<string, unique_ptr<Widget>(*)(const json&)>& widget_builders)
{
widget_builders["image"] = &WidgetImage::builder;
widget_builders["rect"] = &WidgetRect::builder;
widget_builders["text"] = &WidgetText::builder;
}
int main(int argc, char **argv)
{
int result = 0;
bool ok;
int screen_width = 800;
int screen_height = 480;
string output_filename = "trmnl.png";
string cfg_filename = "config.json";
json cfg;
SDL_Surface* main_surface = nullptr;
vector<json> widgets_cfg;
vector<shared_ptr<Widget>> widgets;
map<string, unique_ptr<Widget>(*)(const json&)> widget_builders;
ok = init_sdl();
if (!ok)
{
return -1;
}
if (argc > 1)
{
cfg_filename = argv[1];
}
// Read JSON CFG
ok = read_config_json(cfg, cfg_filename);
if (!ok)
{
result = -1;
goto cleanup;
}
// Change screen size from JSON
json_extract(cfg, "width", screen_width);
json_extract(cfg, "height", screen_height);
json_extract(cfg, "font", default_font_name);
// Create surface
main_surface = SDL_CreateRGBSurfaceWithFormat(0, screen_width, screen_height, 32, SDL_PIXELFORMAT_RGBA8888);
if (nullptr == main_surface)
{
cout << "Could not allocate main surface" << endl;
result = -1;
goto cleanup;
}
init_builders(widget_builders);
// Add Widgets From JSON
if (cfg.contains("widgets") && cfg["widgets"].is_array())
{
widgets_cfg = cfg["widgets"];
}
for (const json& j : widgets_cfg)
{
string widget_name;
json_extract(j, "name", widget_name);
if (widget_name.empty())
{
continue;
}
// Check if name exists in known builders
if (0 == widget_builders.count(widget_name))
{
cout << "Unknown widget '" << widget_name << "'. Skipping ..." << endl;
continue;
}
// Construct and add widget to vector
shared_ptr<Widget> widget = widget_builders[widget_name](j);
if (nullptr != widget)
{
widgets.push_back(widget);
}
}
// Clear screen with white
SDL_FillRect(main_surface, nullptr, SDL_MapRGBA(main_surface->format, 255, 255, 255, SDL_ALPHA_OPAQUE));
// Draw and apply all widgets
for (shared_ptr<Widget>& widget : widgets)
{
widget->draw();
SDL_Rect rect = widget->get_rect();
SDL_BlitSurface(widget->get_internal_surface(), nullptr, main_surface, &rect);
}
// Save image
json_extract(cfg, "output", output_filename);
IMG_SavePNG(main_surface, output_filename.c_str());
cleanup:
widgets.clear();
clean_sdl();
return result;
}