Line data Source code
1 : /**
2 : * @file renderttf.cpp
3 : * @brief SDL2_TTF text renderer
4 : *
5 : * This file implements the wrapper functions needed to use SDL_TTF in the applications
6 : * where Tessfont/rendertext.cpp would have been used, allowing for any TTF font and
7 : * any Unicode character to be renderered at any font size, which are all limitations
8 : * of the legacy Tessfont font sampling system.
9 : *
10 : */
11 : #include "SDL_ttf.h"
12 :
13 : #include "../libprimis-headers/cube.h"
14 : #include "../../shared/geomexts.h"
15 : #include "../../shared/glemu.h"
16 : #include "../../shared/glexts.h"
17 :
18 : #include "rendergl.h"
19 : #include "rendertext.h"
20 : #include "renderttf.h"
21 : #include "shader.h"
22 : #include "shaderparam.h"
23 : #include "texture.h"
24 : #include "renderwindow.h"
25 :
26 : TTFRenderer ttr;
27 :
28 0 : bool TTFRenderer::initttf()
29 : {
30 0 : if(TTF_Init() < 0)
31 : {
32 0 : return false;
33 : }
34 0 : return true;
35 : }
36 :
37 0 : void TTFRenderer::openfont(const char * inpath, int size)
38 : {
39 0 : f = TTF_OpenFont(inpath, size);
40 0 : TTF_SetFontStyle(f, TTF_STYLE_NORMAL);
41 0 : TTF_SetFontOutline(f, 0);
42 0 : TTF_SetFontKerning(f, 1);
43 0 : TTF_SetFontHinting(f, TTF_HINTING_NORMAL);
44 0 : fontcache[size] = f;
45 0 : path = inpath;
46 0 : }
47 :
48 0 : std::string TTFRenderer::trimstring(std::string msg)
49 : {
50 : for(;;)
51 : {
52 0 : size_t itr = msg.find("^f");
53 0 : if(itr < msg.size())
54 : {
55 0 : msg.erase(itr, 3);
56 : }
57 : else
58 : {
59 0 : break;
60 : }
61 0 : }
62 0 : return msg;
63 : }
64 :
65 0 : void TTFRenderer::renderttf(const char* message, SDL_Color col, int x, int y, float scale, uint wrap) const
66 : {
67 0 : std::string msg = std::string(message);
68 :
69 0 : if(!msg.size())
70 : {
71 0 : return;
72 : }
73 :
74 0 : msg = trimstring(msg);
75 :
76 0 : TTFSurface tex = renderttfgl(msg.c_str(), col, wrap);
77 0 : if(tex.tex)
78 : {
79 0 : const float w = tex.w*scale,
80 0 : h = tex.h*scale;
81 0 : SETSHADER(hudrect);
82 0 : gle::colorf(1, 1, 1, 1);
83 0 : const int tw = tex.w,
84 0 : th = tex.h;
85 0 : gle::defvertex(2);
86 0 : gle::deftexcoord0();
87 0 : gle::begin(GL_TRIANGLE_STRIP);
88 0 : gle::attribf(x+w, y); gle::attribf(tw, 0);
89 0 : gle::attribf(x, y); gle::attribf(0, 0);
90 0 : gle::attribf(x+w,y+h); gle::attribf(tw, th);
91 0 : gle::attribf(x,y+h); gle::attribf(0, th);
92 0 : gle::end();
93 : //clean up
94 0 : hudshader->set();
95 0 : glDeleteTextures(1, &(tex.tex));
96 : }
97 : else
98 : {
99 0 : printf("failed to render text: %s\n", message);
100 : }
101 0 : }
102 :
103 0 : void TTFRenderer::ttfbounds(std::string_view str, float &width, float &height, int pts)
104 : {
105 0 : fontsize(pts);
106 0 : ivec2 size = ttfsize(str);
107 0 : width = size.x();
108 0 : height = size.y();
109 0 : }
110 :
111 0 : ivec2 TTFRenderer::ttfsize(std::string_view message)
112 : {
113 0 : if(!std::strlen(message.data()))
114 : {
115 0 : return ivec2(0,0);
116 : }
117 0 : std::string msg = trimstring(std::string(message));
118 : int x, y;
119 0 : TTF_SizeUTF8(f, msg.c_str(), &x, &y);
120 0 : return ivec2(x,y);
121 0 : }
122 :
123 0 : TTFRenderer::TTFSurface TTFRenderer::renderttfgl(const char* message, SDL_Color col, uint wrap) const
124 : {
125 0 : if(!message)
126 : {
127 0 : return {0, 0, 0};
128 : }
129 0 : SDL_Color rgbcol = {col.b, col.g, col.r, 0};
130 0 : SDL_Surface* text = TTF_RenderUTF8_Blended_Wrapped(f, message, rgbcol, wrap);
131 : TTFSurface tts;
132 0 : if(text)
133 : {
134 0 : GLuint tex = 0;
135 0 : glEnable(GL_BLEND);
136 0 : glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
137 0 : glGenTextures(1, &tex);
138 0 : glBindTexture(GL_TEXTURE_RECTANGLE, tex);
139 : //need to load it in reversed because of how SDL_ttf renders
140 0 : glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, text->pitch/4, text->h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, text->pixels);
141 0 : tts = {tex, text->w, text->h};
142 : }
143 : else //empty string may cause this
144 : {
145 0 : tts = {0, 0, 0};
146 : }
147 0 : SDL_FreeSurface(text);
148 0 : return tts;
149 : }
150 :
151 0 : void TTFRenderer::fontsize(int pts)
152 : {
153 0 : std::map<int, TTF_Font *>::iterator itr = fontcache.find(pts);
154 0 : if(itr == fontcache.end())
155 : {
156 0 : TTF_Font* newfont = TTF_OpenFont(path, pts);
157 0 : TTF_SetFontStyle(newfont, TTF_STYLE_NORMAL);
158 0 : TTF_SetFontOutline(newfont, 0);
159 0 : TTF_SetFontKerning(newfont, 1);
160 0 : TTF_SetFontHinting(newfont, TTF_HINTING_NORMAL);
161 0 : fontcache[pts] = newfont;
162 0 : f = newfont;
163 : }
164 : else
165 : {
166 0 : f = fontcache[pts];
167 : }
168 0 : }
|