Something went wrong. Try again.
art software for the rest of us
drawing paint image sdl art
Something went wrong. Try again.
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152#include "Text.h"#include "../Assets.h"#include "../UserInterface/Engine/Scale.h"#include "../UserInterface/Primitives.h"#include <SDL3_ttf/SDL_ttf.h>
// Static member initializations - all at the topTTF_Font* Text::font = nullptr;TTF_Font* Text::iconFont = nullptr;float Text::fontScale = 0.0f;float Text::iconFontScale = 0.0f;
constexpr float BaseFontPoint = 16.0f;constexpr float BaseIconFontPoint = 24.0f;
void Text::Init() { EnsureFonts();}
void Text::EnsureFonts() { // fonts are rasterized at base size * ui scale so glyphs land on real // device pixels instead of getting stretched at draw time const float scale = UI::GetScale(); if (!font) { if (!TTF_Init()) { SDL_Log("TTF_Init failed: %s", SDL_GetError()); return; } font = TTF_OpenFont(Assets::Path("fonts/lexend.ttf").data(), BaseFontPoint * scale); fontScale = scale; if (!font) { SDL_Log("TTF_OpenFont failed: %s", SDL_GetError()); } } else if (fontScale != scale) { TTF_SetFontSize(font, BaseFontPoint * scale); fontScale = scale; }
if (!iconFont) { iconFont = TTF_OpenFont(Assets::Path("fonts/materialSymbolsRounded.ttf").data(), BaseIconFontPoint * scale); iconFontScale = scale; if (!iconFont) { SDL_Log("TTF_OpenFont failed: %s", SDL_GetError()); } } else if (iconFontScale != scale) { TTF_SetFontSize(iconFont, BaseIconFontPoint * scale); iconFontScale = scale; }}
Text::Text(double x, double y, std::string content, TTF_Font* font) : x(x), y(y), content(content), overriddenFont(font) { Init(); createTexture();
}
void Text::SetText(const std::string& newContent) { if (content == newContent) { return; }
content = newContent; delete texture; texture = nullptr; createTexture();
}
void Text::SetPosition(double newX, double newY) { x = newX; y = newY;}
void Text::createTexture() { EnsureFonts(); if (!font) return; SDL_Surface* surface = TTF_RenderText_Blended(overriddenFont ? overriddenFont : font, content.c_str(), content.length(), {255, 255, 255, 255}); if (!surface) { SDL_Log("TTF_RenderText_Blended failed: %s", SDL_GetError()); return; }
SDL_Surface* converted = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888); SDL_DestroySurface(surface); if (!converted) return;
SDL_GPUTextureCreateInfo createInfo = {}; createInfo.type = SDL_GPU_TEXTURETYPE_2D; createInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; createInfo.width = converted->w; createInfo.height = converted->h; createInfo.layer_count_or_depth = 1; createInfo.num_levels = 1; createInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
texture = new Texture(createInfo); texture->Upload(converted->pixels); textureScale = UI::GetScale(); SDL_DestroySurface(converted);}
void Text::SetColor(double r, double g, double b, double a) { this->r = r; this->g = g; this->b = b; this->a = a;
}
void Text::Render() { // the ui scale moved since this was rasterized, redo it crisp if (texture && textureScale != UI::GetScale()) { delete texture; texture = nullptr; } if (!texture) { createTexture(); } if (!texture) return;
UI::Primitives::SubmitText( texture, UI::Rect( static_cast<float>(x), static_cast<float>(y), UI::PixelsToUnits(static_cast<float>(texture->GetWidth())), UI::PixelsToUnits(static_cast<float>(texture->GetHeight())) ), UI::Color(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a)) );}
UI::Size Text::Measure(std::string content) { EnsureFonts(); if (!font) return { 0.0f, 0.0f }; int width; TTF_MeasureString(font, content.c_str(), strlen(content.c_str()), 0, &width, nullptr); return { UI::PixelsToUnits(static_cast<float>(width)), UI::PixelsToUnits(static_cast<float>(TTF_GetFontHeight(font))) };}
TTF_Font* Text::GetIconFont() { EnsureFonts(); return iconFont;}
Text::~Text() { delete texture;}