diff --git a/Widgets/WidgetText.cpp b/Widgets/WidgetText.cpp index f160c65..a3c98d8 100644 --- a/Widgets/WidgetText.cpp +++ b/Widgets/WidgetText.cpp @@ -15,6 +15,72 @@ static SDL_Surface* render_text(bool should_wrap, TTF_Font* font, const string& return txt_surface; } +static SDL_Rect find_visible_area(const SDL_Surface* txt_surface) +{ + int x_start = -1; + int x_end = -1; + int y_start = -1; + int y_end = -1; + + for (int y = 0; y < txt_surface->h; ++y) + { + bool found = false; + for (int x = 0; x < txt_surface->w; ++x) + { + if (1 == (static_cast(txt_surface->pixels)[y * txt_surface->pitch + x])) + { + if (-1 == x_start) + { + x_start = x; + } + else + { + if (x < x_start) + { + x_start = x; + } + } + + if (-1 == x_end) + { + x_end = x; + } + else + { + if (x > x_end) + { + x_end = x; + } + } + found = true; + } + } + + if (found) + { + if (-1 == y_start) + { + y_start = y; + } + y_end = y; + } + } + SDL_Rect result = {.x = 0, .y = 0, .w = 0, .h = 0}; + if ((-1 != x_start) && (-1 != x_end)) + { + result.x = x_start; + result.w = x_end - x_start + 1; + } + + if ((-1 != y_start) && (-1 != y_end)) + { + result.y = y_start; + result.h = y_end - y_start + 1; + } + + return result; +} + WidgetText::WidgetText(int x, int y, int width, int height, string text, TextFit fit, bool should_wrap, HorizontalAlign halign, VerticalAlign valign, @@ -171,7 +237,8 @@ void WidgetText::draw() } // Now we have the final rendered text surface - SDL_Rect align = surface_align(m_surface, txt_surface, m_halign, m_valign); + SDL_Rect hint = find_visible_area(txt_surface); + SDL_Rect align = surface_align(m_surface, txt_surface, m_halign, m_valign, &hint); SDL_BlitSurface(txt_surface, NULL, m_surface, &align); SDL_FreeSurface(txt_surface); } diff --git a/sdl_helpers.cpp b/sdl_helpers.cpp index efc9cad..b1023a8 100644 --- a/sdl_helpers.cpp +++ b/sdl_helpers.cpp @@ -77,42 +77,52 @@ TTF_Font* get_font(int size, const string& filename) } SDL_Rect surface_align(const SDL_Surface* base, const SDL_Surface* applied, - HorizontalAlign halign, VerticalAlign valign) + 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; } + 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 = 0; + align.x = -hint.x; break; case HALIGN_CENTER: - align.x = base->w / 2 - applied->w / 2; + align.x = base->w / 2 - hint.x - hint.w / 2; break; case HALIGN_RIGHT: - align.x = base->w - applied->w; + align.x = base->w - (hint.x + hint.w); break; } switch (valign) { case VALIGN_TOP: - align.y = 0; + align.y = -hint.y; break; case VALIGN_CENTER: - align.y = base->h / 2 - applied->h / 2; + align.y = base->h / 2 - hint.y - hint.h / 2; break; case VALIGN_BOTTOM: - align.y = base->h - applied->h; + align.y = base->h - (hint.y + hint.h); break; } diff --git a/sdl_helpers.h b/sdl_helpers.h index f2c1d63..868b0d2 100644 --- a/sdl_helpers.h +++ b/sdl_helpers.h @@ -66,8 +66,9 @@ TTF_Font* get_font(int size, const std::string& filename = default_font_name); // Returns a rect to use during bliting of 2 surfaces // base - surface on which the other is applied to // applied - the surface which will be applied to the other +// hint - rect to hint visible area from applied - can be NULL SDL_Rect surface_align(const SDL_Surface* base, const SDL_Surface* applied, - HorizontalAlign halign, VerticalAlign valign); + HorizontalAlign halign, VerticalAlign valign, const SDL_Rect* hint = nullptr); // Reads the file and tries to parse a JSON file with comments // cfg - output json struct