#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::set_filename(const string& filename) { if (m_image_surface != nullptr) { SDL_FreeSurface(m_image_surface); m_image_surface = nullptr; } m_filename = filename; m_image_surface = IMG_Load(m_filename.c_str()); if (nullptr == m_image_surface) { // TODO: Print errors } } void WidgetImage::set_resize(ImageResize type) { m_resize_type = type; } void WidgetImage::set_halign(HorizontalAlign halign) { m_halign = halign; } void WidgetImage::set_valign(VerticalAlign valign) { m_valign = valign; } void WidgetImage::set_bg_color(SDL_Color bg_color) { m_bg_color = bg_color; } 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; SDL_Surface* scaled_image = nullptr; switch (m_resize_type) { case RESIZE_NONE: align = surface_align(m_surface, m_image_surface, m_halign, m_valign); SDL_BlitSurface(m_image_surface, nullptr, m_surface, &align); break; case RESIZE_FIT: scaled_image = image_scale_fit(); if (nullptr != scaled_image) { align = surface_align(m_surface, scaled_image, m_halign, m_valign); SDL_BlitScaled(scaled_image, nullptr, m_surface, &align); SDL_FreeSurface(scaled_image); } 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); } SDL_Surface* WidgetImage::image_scale_fit() { SDL_Rect align = {.x = 0, .y = 0, .w = 0, .h = 0}; if ((nullptr == m_surface) || (nullptr == m_image_surface)) { return nullptr; } double x_scale = m_surface->w; x_scale /= m_image_surface->w; double y_scale = m_surface->h; y_scale /= m_image_surface->h; // Find smallest scale factor double min_scale = x_scale; if (y_scale < min_scale) { min_scale = y_scale; } // Scale with double in the front and then clamp to int via SDL_Rect align.w = min_scale * m_image_surface->w; align.h = min_scale * m_image_surface->h; SDL_Surface* scaled_image_surface = SDL_CreateRGBSurfaceWithFormat(0, align.w, align.h, 32, SDL_PIXELFORMAT_RGBA8888); if (nullptr == scaled_image_surface) { // TODO: Print Error return nullptr; } SDL_BlitScaled(m_image_surface, nullptr, scaled_image_surface, nullptr); return scaled_image_surface; }