158 lines
4.5 KiB
C++
158 lines
4.5 KiB
C++
/* +-------------------------------------------------------+
|
|
____/ \____ /| Open source game framework licensed to freely use, |
|
|
\ / / | copy, and modify, created for dank.game |
|
|
+--\ ^__^ /--+ | |
|
|
| ~/ \~ | | Download at https://open.shampoo.ooo/shampoo/spacebox |
|
|
| ~~~~~~~~~~~~ | +-------------------------------------------------------+
|
|
| SPACE ~~~~~ | /
|
|
| ~~~~~~~ BOX |/
|
|
+-------------*/
|
|
|
|
#include "Text.hpp"
|
|
|
|
using namespace sb;
|
|
|
|
void Text::bind_textures() const
|
|
{
|
|
try
|
|
{
|
|
Model::bind_textures();
|
|
}
|
|
catch (const std::runtime_error& error)
|
|
{
|
|
std::ostringstream message;
|
|
message << "Error binding textures for " << *this << ": " << error.what();
|
|
throw std::runtime_error(message.str());
|
|
}
|
|
}
|
|
|
|
void Text::content(const std::string& content)
|
|
{
|
|
_content = content;
|
|
}
|
|
|
|
void Text::content(char content)
|
|
{
|
|
_content = "";
|
|
_content += content;
|
|
}
|
|
|
|
const std::string& Text::content() const
|
|
{
|
|
return _content;
|
|
}
|
|
|
|
void Text::foreground(const Color& foreground)
|
|
{
|
|
_foreground = foreground;
|
|
}
|
|
|
|
void Text::background(const Color& background)
|
|
{
|
|
_background = background;
|
|
}
|
|
|
|
void Text::font(std::shared_ptr<TTF_Font> font)
|
|
{
|
|
_font = font;
|
|
}
|
|
|
|
void Text::dimensions(const glm::vec2 &dimensions)
|
|
{
|
|
_dimensions = dimensions;
|
|
}
|
|
|
|
void Text::scaling_quality(GLint quality)
|
|
{
|
|
_scaling_quality = quality;
|
|
}
|
|
|
|
void Text::wrap(int width)
|
|
{
|
|
_wrap = width;
|
|
}
|
|
|
|
void Text::refresh()
|
|
{
|
|
/* Render the text with transparent background as RGBA pixel data using the SDL image library. Apply wrap if it is set. */
|
|
std::shared_ptr<SDL_Surface> blended;
|
|
if (_wrap.has_value())
|
|
{
|
|
blended = std::shared_ptr<SDL_Surface>{TTF_RenderUTF8_Blended_Wrapped(_font.get(), _content.c_str(), _foreground, _wrap.value()), SDL_FreeSurface};
|
|
}
|
|
else
|
|
{
|
|
blended = std::shared_ptr<SDL_Surface>{TTF_RenderUTF8_Blended(_font.get(), _content.c_str(), _foreground), SDL_FreeSurface};
|
|
}
|
|
|
|
/* Composite the rendered text onto a background surface. */
|
|
if (!blended)
|
|
{
|
|
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)
|
|
{
|
|
Log::sdl_error("Could not create container surface for rendered text");
|
|
}
|
|
else
|
|
{
|
|
SDL_FillRect(container.get(), nullptr, _background);
|
|
Box blended_box {0.0f, 0.0f, float(blended->w), float(blended->h), false};
|
|
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)
|
|
{
|
|
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. The texture object is optimized so that it won't reallocate pixel memory if it was previously
|
|
* generated at the same size. */
|
|
texture(0).generate({flipped->w, flipped->h}, GL_RGBA8, _scaling_quality);
|
|
texture(0).load(flipped.get());
|
|
}
|
|
}
|
|
}
|
|
|
|
Text::operator std::string() const
|
|
{
|
|
std::ostringstream message;
|
|
message << "<sb::Text \"" << _content << "\">";
|
|
return message.str();
|
|
}
|
|
|
|
std::ostream& sb::operator<<(std::ostream& out, const Text& text)
|
|
{
|
|
out << std::string(text);
|
|
return out;
|
|
}
|