100 lines
2.8 KiB
C++
100 lines
2.8 KiB
C++
#include "Text.hpp"
|
|
|
|
using namespace sb;
|
|
|
|
void Text::content(const std::string& content)
|
|
{
|
|
_content = content;
|
|
refresh();
|
|
}
|
|
|
|
void Text::foreground(const sb::Color& foreground)
|
|
{
|
|
_foreground = foreground;
|
|
refresh();
|
|
}
|
|
|
|
void Text::background(const sb::Color& background)
|
|
{
|
|
_background = background;
|
|
refresh();
|
|
}
|
|
|
|
void Text::font(std::shared_ptr<TTF_Font> font)
|
|
{
|
|
_font = font;
|
|
refresh();
|
|
}
|
|
|
|
void Text::dimensions(const glm::vec2 &dimensions)
|
|
{
|
|
_dimensions = dimensions;
|
|
refresh();
|
|
}
|
|
|
|
void Text::scaling_quality(GLint quality)
|
|
{
|
|
_scaling_quality = quality;
|
|
refresh();
|
|
}
|
|
|
|
void Text::refresh()
|
|
{
|
|
/* Render the text with transparent background as RGBA pixel data using the SDL image library. */
|
|
std::shared_ptr<SDL_Surface> blended {TTF_RenderText_Blended(_font.get(), _content.c_str(), _foreground), SDL_FreeSurface};
|
|
if (!blended)
|
|
{
|
|
sb::Log::sdl_error("Could not create text");
|
|
}
|
|
else
|
|
{
|
|
/* Use the size of the rendered text unless dimensions has been set. */
|
|
glm::vec2 dimensions;
|
|
if (_dimensions.has_value())
|
|
{
|
|
dimensions = _dimensions.value();
|
|
}
|
|
else
|
|
{
|
|
dimensions = glm::vec2{blended->w, blended->h};
|
|
}
|
|
|
|
/* Create a container surface with the same format as the rendered text that the rendered text will be composited onto. */
|
|
std::shared_ptr<SDL_Surface> container
|
|
{
|
|
SDL_CreateRGBSurfaceWithFormat(0, dimensions.x, dimensions.y, blended->format->BitsPerPixel, blended->format->format),
|
|
SDL_FreeSurface
|
|
};
|
|
|
|
if (!container)
|
|
{
|
|
sb::Log::sdl_error("Could not create container surface for rendered text");
|
|
}
|
|
else
|
|
{
|
|
SDL_FillRect(container.get(), nullptr, _background);
|
|
sb::Box blended_box {0.0f, 0.0f, float(blended->w), float(blended->h), false};
|
|
sb::Box container_box {0.0f, 0.0f, float(container->w), float(container->h), false};
|
|
blended_box.center(container_box.center());
|
|
SDL_Rect r = blended_box;
|
|
SDL_BlitSurface(blended.get(), nullptr, container.get(), &r);
|
|
blended = container;
|
|
}
|
|
|
|
/* Rotate and mirror the surface for compatibility with OpenGL */
|
|
std::shared_ptr<SDL_Surface> flipped {rotozoomSurfaceXY(blended.get(), 0, 1, -1, 0), SDL_FreeSurface};
|
|
|
|
if (!flipped)
|
|
{
|
|
sb::Log::sdl_error("Could not flip surface");
|
|
}
|
|
else
|
|
{
|
|
/* Generate texture and create storage. Load pixels from the text rendering surface into the texture. The texture object will handle
|
|
* destroying the previous texture. */
|
|
texture().generate({flipped->w, flipped->h}, GL_RGBA8, _scaling_quality);
|
|
texture().load(flipped.get());
|
|
}
|
|
}
|
|
}
|