26 #include <SDL3_ttf/SDL_ttf.h>
28 #include "sdl_widget.hpp"
29 #include "../sdl_utils.hpp"
31 #include "res/sdl3_resource_manager.hpp"
33 #include <freerdp/log.h>
35 #if defined(WITH_SDL_IMAGE_DIALOGS)
36 #include <SDL3_image/SDL_image.h>
39 #define TAG CLIENT_TAG("SDL.widget")
41 static const SDL_Color backgroundcolor = { 0x38, 0x36, 0x35, 0xff };
43 static const Uint32 hpadding = 10;
45 SdlWidget::SdlWidget(SDL_Renderer* renderer,
const SDL_FRect& rect,
bool input)
46 : _rect(rect), _input(input)
51 "OpenSans-VariableFont_wdth,wght.ttf");
53 widget_log_error(-1,
"SDLResourceManager::get");
56 _font = TTF_OpenFontIO(ops,
true, 64);
58 widget_log_error(-1,
"TTF_OpenFontRW");
62 #if defined(WITH_SDL_IMAGE_DIALOGS)
63 SdlWidget::SdlWidget(SDL_Renderer* renderer,
const SDL_FRect& rect, SDL_IOStream* ops) : _rect(rect)
67 _image = IMG_LoadTexture_IO(renderer, ops, 1);
69 widget_log_error(-1,
"IMG_LoadTexture_IO");
74 SdlWidget::SdlWidget(
SdlWidget&& other) noexcept
75 : _font(other._font), _image(other._image), _rect(other._rect), _input(other._input),
76 _wrap(other._wrap), _text_width(other._text_width)
78 other._font =
nullptr;
79 other._image =
nullptr;
82 SDL_Texture* SdlWidget::render_text(SDL_Renderer* renderer,
const std::string& text,
83 SDL_Color fgcolor, SDL_FRect& src, SDL_FRect& dst)
85 auto surface = TTF_RenderText_Blended(_font, text.c_str(), 0, fgcolor);
88 widget_log_error(-1,
"TTF_RenderText_Blended");
92 auto texture = SDL_CreateTextureFromSurface(renderer, surface);
93 SDL_DestroySurface(surface);
96 widget_log_error(-1,
"SDL_CreateTextureFromSurface");
100 std::unique_ptr<TTF_TextEngine, decltype(&TTF_DestroySurfaceTextEngine)> engine(
101 TTF_CreateRendererTextEngine(renderer), TTF_DestroySurfaceTextEngine);
104 widget_log_error(-1,
"TTF_CreateRendererTextEngine");
108 std::unique_ptr<TTF_Text, decltype(&TTF_DestroyText)> txt(
109 TTF_CreateText(engine.get(), _font, text.c_str(), text.size()), TTF_DestroyText);
113 widget_log_error(-1,
"TTF_CreateText");
118 if (!TTF_GetTextSize(txt.get(), &w, &h))
120 widget_log_error(-1,
"TTF_GetTextSize");
124 src.w =
static_cast<float>(w);
125 src.h =
static_cast<float>(h);
133 dst.w -= 2 * hpadding;
134 const float scale = dst.h / src.h;
135 const float sws = (src.w) * scale;
136 const float dws = (dst.w) / scale;
137 dst.w = std::min(dst.w, sws);
146 static float scale(
float dw,
float dh)
148 const auto scale = dh / dw;
149 const auto dr = dh * scale;
153 SDL_Texture* SdlWidget::render_text_wrapped(SDL_Renderer* renderer,
const std::string& text,
154 SDL_Color fgcolor, SDL_FRect& src, SDL_FRect& dst)
156 assert(_text_width < INT32_MAX);
158 auto surface = TTF_RenderText_Blended_Wrapped(_font, text.c_str(), 0, fgcolor,
159 static_cast<int>(_text_width));
162 widget_log_error(-1,
"TTF_RenderText_Blended");
166 src.w =
static_cast<float>(surface->w);
167 src.h =
static_cast<float>(surface->h);
169 auto texture = SDL_CreateTextureFromSurface(renderer, surface);
170 SDL_DestroySurface(surface);
173 widget_log_error(-1,
"SDL_CreateTextureFromSurface");
184 dst.w -= 2 * hpadding;
185 auto dh = scale(src.w, src.h);
186 dst.h = std::min<float>(dh, dst.h);
191 SdlWidget::~SdlWidget()
193 TTF_CloseFont(_font);
195 SDL_DestroyTexture(_image);
198 bool SdlWidget::error_ex(Sint32 res,
const char* what,
const char* file,
size_t line,
201 static wLog* log =
nullptr;
204 return sdl_log_error_ex(res, log, what, file, line, fkt);
207 static bool draw_rect(SDL_Renderer* renderer,
const SDL_FRect* rect, SDL_Color color)
209 const int drc = SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
210 if (widget_log_error(drc,
"SDL_SetRenderDrawColor"))
213 const int rc = SDL_RenderFillRect(renderer, rect);
214 return !widget_log_error(rc,
"SDL_RenderFillRect");
217 bool SdlWidget::fill(SDL_Renderer* renderer, SDL_Color color)
219 std::vector<SDL_Color> colors = { color };
220 return fill(renderer, colors);
223 bool SdlWidget::fill(SDL_Renderer* renderer,
const std::vector<SDL_Color>& colors)
226 SDL_BlendMode mode = SDL_BLENDMODE_INVALID;
227 SDL_GetRenderDrawBlendMode(renderer, &mode);
228 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
229 for (
auto color : colors)
231 draw_rect(renderer, &_rect, color);
232 SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_ADD);
234 SDL_SetRenderDrawBlendMode(renderer, mode);
238 bool SdlWidget::update_text(SDL_Renderer* renderer,
const std::string& text, SDL_Color fgcolor,
243 if (!fill(renderer, bgcolor))
245 return update_text(renderer, text, fgcolor);
248 bool SdlWidget::wrap()
const
253 bool SdlWidget::set_wrap(
bool wrap,
size_t width)
260 const SDL_FRect& SdlWidget::rect()
const
265 bool SdlWidget::update_text(SDL_Renderer* renderer,
const std::string& text, SDL_Color fgcolor)
274 SDL_Texture* texture =
nullptr;
279 auto propId = SDL_GetTextureProperties(_image);
280 auto w = SDL_GetNumberProperty(propId, SDL_PROP_TEXTURE_WIDTH_NUMBER, -1);
281 auto h = SDL_GetNumberProperty(propId, SDL_PROP_TEXTURE_HEIGHT_NUMBER, -1);
283 widget_log_error(-1,
"SDL_GetTextureProperties");
284 src.w =
static_cast<float>(w);
285 src.h =
static_cast<float>(h);
288 texture = render_text_wrapped(renderer, text, fgcolor, src, dst);
290 texture = render_text(renderer, text, fgcolor, src, dst);
294 const int rc = SDL_RenderTexture(renderer, texture, &src, &dst);
296 SDL_DestroyTexture(texture);
298 return !widget_log_error(rc,
"SDL_RenderCopy");
302 bool clear_window(SDL_Renderer* renderer)
306 const int drc = SDL_SetRenderDrawColor(renderer, backgroundcolor.r, backgroundcolor.g,
307 backgroundcolor.b, backgroundcolor.a);
308 if (widget_log_error(drc,
"SDL_SetRenderDrawColor"))
311 const int rcls = SDL_RenderClear(renderer);
312 return !widget_log_error(rcls,
"SDL_RenderClear");
static SDL_IOStream * get(const std::string &type, const std::string &id)
static std::string typeFonts()