#include "WidgetText.h" using std::string; static SDL_Surface* render_text(bool should_wrap, TTF_Font* font, const string& text, SDL_Color color, Uint32 wrap_size) { SDL_Surface* txt_surface = nullptr; if (!should_wrap) { // When wrap_size is 0 - the text only wraps on newlines wrap_size = 0; } txt_surface = TTF_RenderUTF8_Solid_Wrapped(font, text.c_str(), color, wrap_size); return txt_surface; } WidgetText::WidgetText(int x, int y, int width, int height, string text, TextFit fit, bool should_wrap, HorizontalAlign halign, VerticalAlign valign, SDL_Color text_color, int size, std::string font) : Widget(x, y, width, height), m_text(text), m_font_file(font), m_size(size), m_fit(fit), m_should_wrap(should_wrap), m_halign(halign), m_valign(valign), m_text_color(text_color) { if (nullptr != m_surface) { SDL_SetSurfaceBlendMode(m_surface, SDL_BLENDMODE_BLEND); } } WidgetText::WidgetText(int x, int y, int width, int height, string text, TextFit fit, bool should_wrap, int size, string font) : Widget(x, y, width, height), m_text(text), m_font_file(font), m_size(size), m_fit(fit), m_should_wrap(should_wrap), m_halign(HALIGN_CENTER), m_valign(VALIGN_CENTER), m_text_color{.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE} { if (nullptr != m_surface) { SDL_SetSurfaceBlendMode(m_surface, SDL_BLENDMODE_BLEND); } } WidgetText::WidgetText(int x, int y, int width, int height, string text, int size, string font) : Widget(x, y, width, height), m_text(text), m_font_file(font), m_size(size), m_fit(FIT_NONE), m_halign(HALIGN_CENTER), m_valign(VALIGN_CENTER), m_text_color{.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE} { if (nullptr != m_surface) { SDL_SetSurfaceBlendMode(m_surface, SDL_BLENDMODE_BLEND); } } void WidgetText::set_text(const string& text) { m_text = text; } void WidgetText::set_font(const string& font_file) { m_font_file = font_file; } void WidgetText::set_font_size(int size) { m_size = size; } void WidgetText::set_fit(TextFit fit) { m_fit = fit; } void WidgetText::set_halign(HorizontalAlign halign) { m_halign = halign; } void WidgetText::set_valign(VerticalAlign valign) { m_valign = valign; } void WidgetText::set_color(SDL_Color text_color) { m_text_color = text_color; } void WidgetText::draw() { // Clear surface SDL_FillRect(m_surface, nullptr, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT)); string font_name = m_font_file; if (font_name.empty()) { font_name = default_font_name; } TTF_Font* font = get_font(m_size, font_name); if (nullptr == font) { // TODO: Message printing return; } // Render text SDL_Surface* txt_surface = render_text(m_should_wrap, font, m_text, m_text_color, m_rect.w); if (nullptr == txt_surface) { // TODO: Message printing return; } // Check if text fits if (m_fit != FIT_NONE) { double x_scale; double y_scale; x_scale = m_surface->w; x_scale /= txt_surface->w; y_scale = m_surface->h; y_scale /= txt_surface->h; // Find the scale needed to shrink or enlarge with double min_scale = x_scale; if (y_scale < min_scale) { min_scale = y_scale; } // Do not scale up if only shrinkage is allowed if ((min_scale > 1.0) && (FIT_SHRINK == m_fit)) { min_scale = 1.0; } // Find new font size int new_text_size = m_size; new_text_size *= min_scale; // Re-render text if (new_text_size != m_size) { SDL_FreeSurface(txt_surface); font = get_font(new_text_size, font_name); if (nullptr == font) { // TODO: Message printing return; } txt_surface = render_text(m_should_wrap, font, m_text, m_text_color, m_rect.w); if (nullptr == txt_surface) { // TODO: Message printing return; } } } // Now we have the final rendered text surface SDL_Rect align = surface_align(m_surface, txt_surface, m_halign, m_valign); SDL_BlitSurface(txt_surface, NULL, m_surface, &align); SDL_FreeSurface(txt_surface); } Widget* WidgetText::builder(const nlohmann::json& j) { int x = 0; int y = 0; int width = 0; int height = 0; string text = ""; TextFit fit = FIT_NONE; bool should_wrap = false; HorizontalAlign halign = HALIGN_CENTER; VerticalAlign valign = VALIGN_CENTER; SDL_Color text_color = {.r = 0, .g = 0, .b = 0, .a = SDL_ALPHA_OPAQUE}; int size = 0; string font = ""; json_extract(j, "x", x); json_extract(j, "y", y); json_extract(j, "width", width); json_extract(j, "height", height); json_extract(j, "text", text); json_extract(j, "fit", fit); json_extract(j, "should_wrap", should_wrap); json_extract(j, "halign", halign); json_extract(j, "valign", valign); json_extract(j, "color", text_color); json_extract(j, "size", size); json_extract(j, "font", font); if ((0 == width) || (0 == height) || (0 == size)) { return nullptr; } return new WidgetText(x, y, width, height, text, fit, should_wrap, halign, valign, text_color, size, font); }