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