26#include <SDL3_ttf/SDL_ttf.h> 
   28#include "sdl_widget.hpp" 
   29#include "sdl_blend_mode_guard.hpp" 
   30#include "../sdl_utils.hpp" 
   32#include "res/sdl3_resource_manager.hpp" 
   34#include <freerdp/log.h> 
   36#if defined(WITH_SDL_IMAGE_DIALOGS) 
   37#include <SDL3_image/SDL_image.h> 
   40#define TAG CLIENT_TAG("SDL.widget") 
   42static const Uint32 hpadding = 10;
 
   44SdlWidget::SdlWidget(std::shared_ptr<SDL_Renderer>& renderer, 
const SDL_FRect& rect)
 
   45    : _renderer(renderer),
 
   46      _engine(TTF_CreateRendererTextEngine(renderer.get()), TTF_DestroyRendererTextEngine),
 
   52                                      "OpenSans-VariableFont_wdth,wght.ttf");
 
   54    widget_log_error(
false, 
"SDLResourceManager::get");
 
   57    _font = std::shared_ptr<TTF_Font>(TTF_OpenFontIO(ops, 
true, 64), TTF_CloseFont);
 
   59      widget_log_error(
false, 
"TTF_OpenFontRW");
 
   63#if defined(WITH_SDL_IMAGE_DIALOGS) 
   64SdlWidget::SdlWidget(std::shared_ptr<SDL_Renderer>& renderer, 
const SDL_FRect& rect,
 
   66    : _renderer(renderer),
 
   67      _engine(TTF_CreateRendererTextEngine(renderer.get()), TTF_DestroySurfaceTextEngine),
 
   72    _image = std::shared_ptr<SDL_Texture>(IMG_LoadTexture_IO(renderer.get(), ops, 1),
 
   75      widget_log_error(
false, 
"IMG_LoadTexture_IO");
 
   80SdlWidget::SdlWidget(
SdlWidget&& other) noexcept
 
   81    : _renderer(std::move(other._renderer)), _backgroundcolor(other._backgroundcolor),
 
   82      _fontcolor(other._fontcolor), _text(std::move(other._text)), _font(std::move(other._font)),
 
   83      _image(std::move(other._image)), _engine(std::move(other._engine)), _rect(other._rect),
 
   84      _wrap(other._wrap), _text_width(other._text_width)
 
   86  other._font = 
nullptr;
 
   87  other._image = 
nullptr;
 
   88  other._engine = 
nullptr;
 
   91std::shared_ptr<SDL_Texture> SdlWidget::render_text(
const std::string& text, SDL_Color fgcolor,
 
   92                                                    SDL_FRect& src, SDL_FRect& dst)
 const 
   94  auto surface = std::shared_ptr<SDL_Surface>(
 
   95      TTF_RenderText_Blended(_font.get(), text.c_str(), 0, fgcolor), SDL_DestroySurface);
 
   98    widget_log_error(
false, 
"TTF_RenderText_Blended");
 
  102  auto texture = std::shared_ptr<SDL_Texture>(
 
  103      SDL_CreateTextureFromSurface(_renderer.get(), surface.get()), SDL_DestroyTexture);
 
  106    widget_log_error(
false, 
"SDL_CreateTextureFromSurface");
 
  112    widget_log_error(
false, 
"TTF_CreateRendererTextEngine");
 
  116  std::unique_ptr<TTF_Text, 
decltype(&TTF_DestroyText)> txt(
 
  117      TTF_CreateText(_engine.get(), _font.get(), text.c_str(), text.size()), TTF_DestroyText);
 
  121    widget_log_error(
false, 
"TTF_CreateText");
 
  126  if (!TTF_GetTextSize(txt.get(), &w, &h))
 
  128    widget_log_error(
false, 
"TTF_GetTextSize");
 
  132  src.w = 
static_cast<float>(w);
 
  133  src.h = 
static_cast<float>(h);
 
  141  dst.w -= 2 * hpadding;
 
  142  const float scale = dst.h / src.h;
 
  143  const float sws = (src.w) * scale;
 
  144  const float dws = (dst.w) / scale;
 
  145  dst.w = std::min(dst.w, sws);
 
  154static float scale(
float dw, 
float dh)
 
  156  const auto scale = dh / dw;
 
  157  const auto dr = dh * scale;
 
  161std::shared_ptr<SDL_Texture> SdlWidget::render_text_wrapped(
const std::string& text,
 
  162                                                            SDL_Color fgcolor, SDL_FRect& src,
 
  163                                                            SDL_FRect& dst)
 const 
  165  assert(_text_width < INT32_MAX);
 
  167  auto surface = std::shared_ptr<SDL_Surface>(
 
  168      TTF_RenderText_Blended_Wrapped(_font.get(), text.c_str(), 0, fgcolor,
 
  169                                     static_cast<int>(_text_width)),
 
  173    widget_log_error(
false, 
"TTF_RenderText_Blended");
 
  177  src.w = 
static_cast<float>(surface->w);
 
  178  src.h = 
static_cast<float>(surface->h);
 
  180  auto texture = std::shared_ptr<SDL_Texture>(
 
  181      SDL_CreateTextureFromSurface(_renderer.get(), surface.get()), SDL_DestroyTexture);
 
  184    widget_log_error(
false, 
"SDL_CreateTextureFromSurface");
 
  195  dst.w -= 2 * hpadding;
 
  196  auto dh = scale(src.w, src.h);
 
  197  dst.h = std::min<float>(dh, dst.h);
 
  202SdlWidget::~SdlWidget() = 
default;
 
  204bool SdlWidget::error_ex(
bool success, 
const char* what, 
const char* file, 
size_t line,
 
  212  static wLog* log = 
nullptr;
 
  217  return sdl_log_error_ex(-1, log, what, file, line, fkt);
 
  220bool SdlWidget::updateInternal()
 
  222  return update_text(_text);
 
  225bool SdlWidget::draw_rect(
const SDL_FRect& rect, SDL_Color color)
 const 
  227  const auto drc = SDL_SetRenderDrawColor(_renderer.get(), color.r, color.g, color.b, color.a);
 
  228  if (widget_log_error(drc, 
"SDL_SetRenderDrawColor"))
 
  231  const auto rc = SDL_RenderFillRect(_renderer.get(), &rect);
 
  232  return !widget_log_error(rc, 
"SDL_RenderFillRect");
 
  235bool SdlWidget::fill(SDL_Color color)
 const 
  237  std::vector<SDL_Color> colors = { color };
 
  241bool SdlWidget::fill(
const std::vector<SDL_Color>& colors)
 const 
  245  for (
auto color : colors)
 
  247    if (!draw_rect(_rect, color))
 
  250    if (!guard.update(SDL_BLENDMODE_ADD))
 
  257bool SdlWidget::wrap()
 const 
  262bool SdlWidget::set_wrap(
bool wrap, 
size_t width)
 
  269const SDL_FRect& SdlWidget::rect()
 const 
  274bool SdlWidget::clear()
 const 
  281  const auto drc = SDL_SetRenderDrawColor(_renderer.get(), _backgroundcolor.r, _backgroundcolor.g,
 
  282                                          _backgroundcolor.b, _backgroundcolor.a);
 
  283  if (widget_log_error(drc, 
"SDL_SetRenderDrawColor"))
 
  286  const auto rcls = SDL_RenderRect(_renderer.get(), &_rect);
 
  287  return !widget_log_error(rcls, 
"SDL_RenderRect");
 
  290bool SdlWidget::update()
 
  295  return updateInternal();
 
  298bool SdlWidget::update_text(
const std::string& text)
 
  307  std::shared_ptr<SDL_Texture> texture;
 
  312    auto propId = SDL_GetTextureProperties(_image.get());
 
  313    auto w = SDL_GetNumberProperty(propId, SDL_PROP_TEXTURE_WIDTH_NUMBER, -1);
 
  314    auto h = SDL_GetNumberProperty(propId, SDL_PROP_TEXTURE_HEIGHT_NUMBER, -1);
 
  316      widget_log_error(
false, 
"SDL_GetTextureProperties");
 
  317    src.w = 
static_cast<float>(w);
 
  318    src.h = 
static_cast<float>(h);
 
  321    texture = render_text_wrapped(_text, _fontcolor, src, dst);
 
  323    texture = render_text(_text, _fontcolor, src, dst);
 
  327  const auto rc = SDL_RenderTexture(_renderer.get(), texture.get(), &src, &dst);
 
  328  return !widget_log_error(rc, 
"SDL_RenderCopy");
 
static SDL_IOStream * get(const std::string &type, const std::string &id)
 
static std::string typeFonts()