diff --git a/Makefile b/Makefile index d5a6d5d..4803741 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,9 @@ src_files += main.cpp src_files += sdl_helpers.cpp src_files += Widgets/Widget.cpp -src_files += Widgets/WidgetText.cpp +src_files += Widgets/WidgetImage.cpp src_files += Widgets/WidgetRect.cpp +src_files += Widgets/WidgetText.cpp all: g++ $(src_files) -Wall -lSDL2 -lSDL2_ttf -lSDL2_image -o trmnl_sdl diff --git a/Widgets/WidgetImage.cpp b/Widgets/WidgetImage.cpp new file mode 100644 index 0000000..a8729e0 --- /dev/null +++ b/Widgets/WidgetImage.cpp @@ -0,0 +1,84 @@ +#include "WidgetImage.h" + +#include + +using std::string; + +WidgetImage::WidgetImage(int x, int y, int width, int height, string filename, + ImageResize resize_type, HorizontalAlign halign, VerticalAlign valign, + SDL_Color bg_color) +: Widget(x, y, width, height), +m_filename(filename), +m_image_surface(nullptr), +m_resize_type(resize_type), +m_halign(halign), +m_valign(valign), +m_bg_color(bg_color) +{ + m_image_surface = IMG_Load(m_filename.c_str()); + + if (nullptr == m_image_surface) + { + // TODO: Print errors + } +} + +void WidgetImage::draw() +{ + if (nullptr == m_surface) + { + return; + } + + // Clear surface with BG color + SDL_FillRect(m_surface, nullptr, + SDL_MapRGBA(m_surface->format, m_bg_color.r, m_bg_color.g, m_bg_color.b, m_bg_color.a)); + + if (nullptr == m_image_surface) + { + return; + } + + SDL_Rect align = surface_align(m_surface, m_image_surface, m_halign, m_valign); + switch (m_resize_type) + { + case RESIZE_NONE: + SDL_BlitSurface(m_image_surface, nullptr, m_surface, &align); + break; + + case RESIZE_FIT: + // TODO: This currently stretches + SDL_BlitScaled(m_image_surface, nullptr, m_surface, nullptr); + break; + + case RESIZE_STRETCH: + SDL_BlitScaled(m_image_surface, nullptr, m_surface, nullptr); + break; + } +} + +std::unique_ptr WidgetImage::builder(const nlohmann::json& j) +{ + int x = 0; + int y = 0; + int width = 0; + int height = 0; + string filename; + ImageResize resize_type = RESIZE_FIT; + HorizontalAlign halign = HALIGN_CENTER; + VerticalAlign valign = VALIGN_CENTER; + SDL_Color bg_color = {.r = 255, .g = 255, .b = 255, .a = SDL_ALPHA_TRANSPARENT}; + + json_extract(j, "x", x); + json_extract(j, "y", y); + json_extract(j, "width", width); + json_extract(j, "height", height); + json_extract(j, "filename", filename); + json_extract(j, "resize_type", resize_type); + json_extract(j, "halign", halign); + json_extract(j, "valign", valign); + json_extract(j, "bg_color", bg_color); + + return std::make_unique(x, y, width, height, filename, + resize_type, halign, valign, bg_color); +} diff --git a/Widgets/WidgetImage.h b/Widgets/WidgetImage.h new file mode 100644 index 0000000..d940444 --- /dev/null +++ b/Widgets/WidgetImage.h @@ -0,0 +1,47 @@ +#ifndef WIDGET_IMAGE_H_ +#define WIDGET_IMAGE_H_ + +#include "Widget.h" + +#include + +#include "../sdl_helpers.h" + +class WidgetImage : public Widget +{ +protected: + // Image filepath + std::string m_filename; + + // Image surface + SDL_Surface* m_image_surface; + + // Whether to resize the image and how + // RESIZE_NONE - Do not resize + // RESIZE_FIT - Scale the image to fit the rectangle + // RESIZE_STRETCH - Scale and stretch the image to fit the box perfectly + ImageResize m_resize_type; + + // Default - center + HorizontalAlign m_halign; + + // Default - center + VerticalAlign m_valign; + + // Background color to be used + // Default - transparent white + SDL_Color m_bg_color; + +public: + WidgetImage(int x, int y, int width, int height, std::string filename, + ImageResize resize_type = RESIZE_FIT, + HorizontalAlign halign = HALIGN_CENTER, + VerticalAlign valign = VALIGN_CENTER, + SDL_Color bg_color = SDL_Color{.r = 255, .g = 255, .b = 255, .a = SDL_ALPHA_TRANSPARENT}); + + virtual void draw() override; + + static std::unique_ptr builder(const nlohmann::json& j); +}; + +#endif // WIDGET_IMAGE_H_ diff --git a/main.cpp b/main.cpp index 1b3ca0b..5973348 100644 --- a/main.cpp +++ b/main.cpp @@ -12,8 +12,9 @@ #include "sdl_helpers.h" #include "Widgets/Widget.h" -#include "Widgets/WidgetText.h" +#include "Widgets/WidgetImage.h" #include "Widgets/WidgetRect.h" +#include "Widgets/WidgetText.h" using std::cout; using std::endl; @@ -26,6 +27,7 @@ using nlohmann::json; void init_builders(map(*)(const json&)>& widget_builders) { + widget_builders["image"] = &WidgetImage::builder; widget_builders["rect"] = &WidgetRect::builder; widget_builders["text"] = &WidgetText::builder; } diff --git a/sdl_helpers.cpp b/sdl_helpers.cpp index b1023a8..03af385 100644 --- a/sdl_helpers.cpp +++ b/sdl_helpers.cpp @@ -167,7 +167,7 @@ void json_extract(const json& j, const string& key, string& out) } } -void json_extract(const nlohmann::json& j, const string& key, int& out) +void json_extract(const json& j, const string& key, int& out) { if (j.contains(key) && j[key].is_number_integer()) { @@ -175,7 +175,7 @@ void json_extract(const nlohmann::json& j, const string& key, int& out) } } -void json_extract(const nlohmann::json& j, const string& key, bool& out) +void json_extract(const json& j, const string& key, bool& out) { if (j.contains(key) && j[key].is_boolean()) { @@ -238,10 +238,24 @@ void json_extract(const json& j, const string& key, SDL_Color& out) } } -void json_extract(const nlohmann::json& j, const string& key, Uint8& out) +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) + { + } + } +} diff --git a/sdl_helpers.h b/sdl_helpers.h index 868b0d2..9a47469 100644 --- a/sdl_helpers.h +++ b/sdl_helpers.h @@ -52,6 +52,20 @@ NLOHMANN_JSON_SERIALIZE_ENUM(TextFit, {FIT_AUTO, "auto"}, }) +enum ImageResize +{ + RESIZE_NONE, + RESIZE_FIT, + RESIZE_STRETCH +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(ImageResize, +{ + {RESIZE_NONE, "none"}, + {RESIZE_FIT, "fit"}, + {RESIZE_STRETCH, "stretch"}, +}) + // Call this before everything // Prints its messages bool init_sdl(); @@ -86,5 +100,6 @@ void json_extract(const nlohmann::json& j, const std::string& key, VerticalAlign void json_extract(const nlohmann::json& j, const std::string& key, TextFit& out); void json_extract(const nlohmann::json& j, const std::string& key, SDL_Color& out); void json_extract(const nlohmann::json& j, const std::string& key, Uint8& out); +void json_extract(const nlohmann::json& j, const std::string& key, ImageResize& out); #endif // SDL_HELPERS_H_