Files
tessesframework/src/SDL2/FontCache.cpp
2025-06-12 15:43:58 -05:00

276 lines
7.1 KiB
C++

#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
#include "TessesFramework/SDL2/FontCache.hpp"
#include "TessesFramework/Http/HttpUtils.hpp"
#include "TessesFramework/TanoheSans-Regular.h"
using HU= Tesses::Framework::Http::HttpUtils;
namespace Tesses::Framework::SDL2 {
void FontCache::Load(SDL_Renderer* renderer,TTF_Font* font)
{
this->mw=0;
this->mh=0;
this->ps=ps;
for(size_t i = 0; i < this->font_chrs.size();i++)
{
SDL_Surface* surf = TTF_RenderGlyph_Blended(font,(Uint16)(i+32),{.r=255,.g=255,.b=255,.a=255});
if(surf->w > this->mw) mw = surf->w;
if(surf->h > this->mh) mh = surf->h;
this->font_chrs[i] = SDL_CreateTextureFromSurface(renderer,surf);
SDL_FreeSurface(surf);
}
}
FontCache::FontCache(SDL_Renderer* renderer,std::string font,int sz)
{
TTF_Font* f = TTF_OpenFont(font.c_str(),sz);
Load(renderer,f);
TTF_CloseFont(f);
}
FontCache::FontCache(SDL_Renderer* renderer,const uint8_t* mem,size_t cnt,int sz)
{
TTF_Font* f = TTF_OpenFontRW(SDL_RWFromConstMem(mem,cnt),1,sz);
Load(renderer,f);
TTF_CloseFont(f);
}
FontCache::FontCache(SDL_Renderer* renderer,const std::vector<uint8_t>& v,int sz) : FontCache(renderer,v.data(),v.size(),sz)
{
}
FontCache::FontCache(SDL_Renderer* renderer,TTF_Font* font)
{
this->Load(renderer,font);
}
FontCache::FontCache(SDL_Renderer* renderer,int sz) : FontCache(renderer,TANOHESANSREGULAR,TANOHESANSREGULAR_SIZE,sz)
{
}
void FontCache::CalculateSize(std::string text, int& x,int& y)
{
int myX = 0;
x=0;
y=0;
int maxH = MaxHeight();
y=maxH;
for(auto c : text)
{
switch(c)
{
case '\n':
{
y += maxH;
if(myX > x) x = myX;
myX = 0;
}
break;
case '\t':
{
auto tex = operator[](' ');
int wi;
SDL_QueryTexture(tex,NULL,NULL,&wi,NULL);
myX += wi * 4;
}
break;
default:
{
auto tex = operator[](c);
int wi;
int he;
SDL_QueryTexture(tex,NULL,NULL,&wi,&he);
myX += wi;
}
break;
}
}
if(myX > x) x = myX;
}
void FontCache::Render(SDL_Renderer* renderer,int x,int y, std::string text,const SDL_Color& color)
{
int myX = x;
int maxH = MaxHeight();
for(auto c : text)
{
switch(c)
{
case '\n':
{
y += maxH;
myX = x;
}
break;
case '\t':
{
auto tex = GetCharOfColor(' ',color);
int wi;
SDL_QueryTexture(tex,NULL,NULL,&wi,NULL);
myX += wi * 4;
}
break;
default:
{
auto tex = GetCharOfColor(c,color);
int wi;
int he;
SDL_QueryTexture(tex,NULL,NULL,&wi,&he);
SDL_Rect src={.x=0,.y=0,.w=wi,.h=he};
SDL_Rect dest={.x=myX,.y=y,.w=wi,.h=he};
myX += wi;
SDL_RenderCopy(renderer,tex,&src,&dest);
}
break;
}
}
}
SDL_Texture* FontCache::GetCharOfColor(char c, const SDL_Color& color)
{
auto res = (c >= 32 && c <= 126) ? this->font_chrs[c-32] : this->font_chrs[95];
SDL_SetTextureColorMod(res,color.r,color.g,color.b);
return res;
}
SDL_Texture* FontCache::operator[](char c)
{
return GetCharOfColor(c,{.r=255,.g=255,.b=255,.a=255});
}
FontCache::~FontCache()
{
for(auto item : this->font_chrs)
SDL_DestroyTexture(item);
}
int FontCache::MaxWidth()
{
return this->mw;
}
int FontCache::MaxHeight()
{
return this->mh;
}
int FontCache::PointSize()
{
return this->ps;
}
bool TryParseSDLColor(std::string str, SDL_Color& col)
{
str = HU::Replace(str," ","");
//rgba(255,255,255,1.0)
//rgb(197, 30, 30)
//#rgb
//#rgba
//#rrggbb
//#rrggbbaa
if(str.size() >= 4 && str[0] == '#')
{
if(str.size() == 4)
{
auto r = HU::HexToNibble(str[1]);
r |= r << 4;
auto g = HU::HexToNibble(str[2]);
g |= g << 4;
auto b = HU::HexToNibble(str[3]);
b |= b << 4;
col.r = r;
col.g = g;
col.b = b;
col.a = 255;
return true;
}
else if(str.size() == 5)
{
auto r = HU::HexToNibble(str[1]);
r |= r << 4;
auto g = HU::HexToNibble(str[2]);
g |= g << 4;
auto b = HU::HexToNibble(str[3]);
b |= b << 4;
auto a = HU::HexToNibble(str[4]);
a |= a << 4;
col.r = r;
col.g = g;
col.b = b;
col.a = a;
return true;
}
else if(str.size() == 7) {
auto r = HU::HexToNibble(str[1]);
r |= HU::HexToNibble(str[2]) << 4;
auto g = HU::HexToNibble(str[3]);
g |= HU::HexToNibble(str[4]) << 4;
auto b = HU::HexToNibble(str[5]);
b |= HU::HexToNibble(str[6]) << 4;
col.r = r;
col.g = g;
col.b = b;
col.a = 255;
return true;
}
else if(str.size() == 9)
{
auto r = HU::HexToNibble(str[1]);
r |= HU::HexToNibble(str[2]) << 4;
auto g = HU::HexToNibble(str[3]);
g |= HU::HexToNibble(str[4]) << 4;
auto b = HU::HexToNibble(str[5]);
b |= HU::HexToNibble(str[6]) << 4;
auto a = HU::HexToNibble(str[7]);
a |= HU::HexToNibble(str[8]) << 4;
col.r = r;
col.g = g;
col.b = b;
col.a = a;
return true;
}
}
else if(str.size() > 4 && strncmp(str.c_str(),"rgb(",4) == 0 && str[str.size()-1] == ')')
{
str = HU::Replace(str.substr(4),")","");
auto parts = HU::SplitString(str,",");
if(parts.size() != 3) return false;
try{
auto r = std::stoul(parts[0]);
auto g = std::stoul(parts[1]);
auto b = std::stoul(parts[2]);
col.r = (Uint8)r;
col.g = (Uint8)g;
col.b = (Uint8)b;
col.a = 255;
} catch(...) {
return false;
}
return true;
}
else if(str.size() > 5 && strncmp(str.c_str(),"rgba(",5) == 0 && str[str.size()-1] == ')')
{
str = HU::Replace(str.substr(5),")","");
auto parts = HU::SplitString(str,",");
if(parts.size() != 4) return false;
try{
auto r = std::stoul(parts[0]);
auto g = std::stoul(parts[1]);
auto b = std::stoul(parts[2]);
double a= std::stod(parts[3]);
col.r = (Uint8)r;
col.g = (Uint8)g;
col.b = (Uint8)b;
col.a = (Uint8)(a * 255);
} catch(...) {
return false;
}
return true;
}
return false;
}
}
#endif