Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / 3d / font_manager.cpp
blob3d468f987ee0eee228269894354553994fdfab85
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include <string>
23 //#include <sstream>
25 #include "nel/3d/font_manager.h"
26 #include "nel/3d/font_generator.h"
27 #include "nel/3d/texture_font.h"
28 #include "nel/3d/computed_string.h"
29 #include "nel/3d/index_buffer.h"
30 #include "nel/3d/material.h"
31 #include "nel/misc/smart_ptr.h"
32 #include "nel/misc/debug.h"
34 #include "nel/misc/file.h"
36 using namespace std;
38 #ifdef DEBUG_NEW
39 #define new DEBUG_NEW
40 #endif
42 namespace NL3D {
46 // ***************************************************************************
47 CMaterial* CFontManager::getFontMaterial()
49 if (_TexFont == NULL)
51 _TexFont = new CTextureFont;
52 _TexCacheNr++;
55 if (_MatFont == NULL)
57 _MatFont= new CMaterial;
58 _MatFont->initUnlit();
59 _MatFont->setSrcBlend(CMaterial::srcalpha);
60 _MatFont->setDstBlend(CMaterial::invsrcalpha);
61 _MatFont->setBlend(true);
62 _MatFont->setTexture(0, _TexFont);
63 _MatFont->texEnvOpRGB(0, CMaterial::Replace);
64 _MatFont->texEnvArg0RGB(0, CMaterial::Diffuse, CMaterial::SrcColor);
66 return _MatFont;
69 // ***************************************************************************
70 void CFontManager::computeString (NLMISC::CUtfStringView sv,
71 CFontGenerator *fontGen,
72 const NLMISC::CRGBA &color,
73 uint32 fontSize,
74 bool embolden,
75 bool oblique,
76 IDriver *driver,
77 CComputedString &output,
78 bool keep800x600Ratio)
80 output.Color = color;
82 // resize fontSize if window not of 800x600.
83 if (keep800x600Ratio)
85 uint32 width, height;
86 driver->getWindowSize (width, height);
87 if ((height == 0) || (width == 0))
88 return;
90 // keep the 800*600 ratio
91 fontSize = (uint32)floor(fontSize*height/600.f);
92 fontSize = max(fontSize, (uint32)2);
95 // Setting vertices format
96 output.Vertices.setNumVertices (4 * (uint32)sv.largestSize());
98 // 1 character <-> 1 quad
99 sint32 penx = 0, dx;
100 sint32 penz = 0, dz;
101 float x1, z1, x2, z2;
102 float u1, v1, u2, v2;
103 CMaterial *pMatFont = getFontMaterial();
104 CTextureFont *pTexFont = (CTextureFont*)(pMatFont->getTexture (0));
105 float TexRatioW = 1.0f / pTexFont->getWidth();
106 float TexRatioH = 1.0f / pTexFont->getHeight();
107 /*float hlfPixTexW = 0.5f * TexRatioW;
108 float hlfPixTexH = 0.5f * TexRatioH;
109 float hlfPixScrW = 0.5f;
110 float hlfPixScrH = 0.5f;*/
111 // Yoyo: Do not need Half Pixel/Texel displacement!!
112 float hlfPixTexW = 0;
113 float hlfPixTexH = 0;
114 float hlfPixScrW = 0;
115 float hlfPixScrH = 0;
118 CTextureFont::SLetterKey k;
120 // string bound.
121 output.XMin= FLT_MAX;
122 output.XMax= -FLT_MAX;
123 output.ZMin= FLT_MAX;
124 output.ZMax= -FLT_MAX;
126 // string info.
127 sint32 nMaxZ = -1000000, nMinZ = 1000000;
128 output.StringHeight = 0;
130 // save string info for later rebuild as needed
131 if (sv.ptr() != output.Text.c_str()) // don't resave if rebuilding
132 output.Text = sv.toUtf8();
133 output.CacheVersion = getCacheVersion();
135 uint j = 0;
136 size_t idx = 0;
138 CVertexBufferReadWrite vba;
139 output.Vertices.lock (vba);
141 hlfPixScrW = 0.f;
142 hlfPixScrH = 0.f;
144 // For all chars
145 for (NLMISC::CUtfStringView::iterator it(sv.begin()), end(sv.end()); it != end; ++it, ++idx)
147 // Creating font
148 k.Char = *it;
149 if (k.Char < 0x20) // Control Characters
150 k.Char += 0x2400;
151 if (k.Char == 0x7F) // DEL
152 k.Char = 0x2421;
153 k.FontGenerator = fontGen;
154 k.Size = fontSize;
155 k.Embolden = embolden;
156 k.Oblique = oblique;
157 // render letter
158 CTextureFont::SLetterInfo *pLI = pTexFont->getLetterInfo (k, true);
159 if(pLI != NULL)
161 if (pLI->glyph)
163 // If letter is heavily upscaled, then there is noticeable clipping on edges
164 // fixing UV will make it bit better
165 if ((pLI->Size >> 1) > pLI->glyph->Size)
167 hlfPixTexW = 0.5f * TexRatioW;
168 hlfPixTexH = 0.5f * TexRatioH;
171 // Creating vertices
172 dx = pLI->Left;
173 dz = -((sint32)pLI->CharHeight - (sint32)(pLI->Top));
175 x1 = (penx + dx) - hlfPixScrW;
176 z1 = (penz + dz) - hlfPixScrH;
177 x2 = (penx + dx + (sint32)pLI->CharWidth) + hlfPixScrW;
178 z2 = (penz + dz + (sint32)pLI->CharHeight) + hlfPixScrH;
180 vba.setVertexCoord (j, x1, 0, z1);
181 vba.setTexCoord (j, 0, pLI->glyph->U0-hlfPixTexW, pLI->glyph->V1+hlfPixTexH);
182 ++j;
184 vba.setVertexCoord (j, x2, 0, z1);
185 vba.setTexCoord (j, 0, pLI->glyph->U1+hlfPixTexW, pLI->glyph->V1+hlfPixTexH);
186 ++j;
188 vba.setVertexCoord (j, x2, 0, z2);
189 vba.setTexCoord (j, 0, pLI->glyph->U1+hlfPixTexW, pLI->glyph->V0-hlfPixTexH);
190 ++j;
192 vba.setVertexCoord (j, x1, 0, z2);
193 vba.setTexCoord (j, 0, pLI->glyph->U0-hlfPixTexW, pLI->glyph->V0-hlfPixTexH);
194 ++j;
196 // String Bound
197 output.XMin= min(output.XMin, x1);
198 output.XMin= min(output.XMin, x2);
199 output.XMax= max(output.XMax, x1);
200 output.XMax= max(output.XMax, x2);
201 output.ZMin= min(output.ZMin, z1);
202 output.ZMin= min(output.ZMin, z2);
203 output.ZMax= max(output.ZMax, z1);
204 output.ZMax= max(output.ZMax, z2);
206 // String info
207 sint32 nZ1 = (sint32)pLI->Top-(sint32)pLI->CharHeight;
208 sint32 nZ2 = pLI->Top;
210 if (nZ1 < nMinZ) nMinZ = nZ1;
211 if (nZ2 > nMaxZ) nMaxZ = nZ2;
213 penx += pLI->AdvX;
216 // Building Material
217 output.Material = pMatFont;
220 output.Vertices.setNumVertices (j);
221 output.Length = idx;
222 nlassert(output.Length == NLMISC::CUtfStringView(output.Text).count());
224 // compile string info
225 output.StringWidth = (float)penx;
226 if(nMaxZ>nMinZ)
228 output.StringHeight = (float)(nMaxZ - nMinZ);
229 output.StringLine = -(float)nMinZ;
231 else
233 output.StringHeight = 0;
234 output.StringLine = 0;
239 // ***************************************************************************
240 void CFontManager::computeStringInfo ( NLMISC::CUtfStringView sv,
241 CFontGenerator *fontGen,
242 const NLMISC::CRGBA &color,
243 uint32 fontSize,
244 bool embolden,
245 bool oblique,
246 IDriver *driver,
247 CComputedString &output,
248 bool keep800x600Ratio )
250 computeStringInfo(sv, sv.largestSize(), fontGen, color, fontSize, embolden, oblique, driver, output, keep800x600Ratio);
254 // ***************************************************************************
255 void CFontManager::computeStringInfo ( NLMISC::CUtfStringView sv,
256 size_t len,
257 CFontGenerator *fontGen,
258 const NLMISC::CRGBA &color,
259 uint32 fontSize,
260 bool embolden,
261 bool oblique,
262 IDriver *driver,
263 CComputedString &output,
264 bool keep800x600Ratio )
266 output.Color = color;
268 // save string info for later rebuild as needed
269 if (sv.ptr() != output.Text.c_str()) // don't resave if rebuilding
270 output.Text = sv.toUtf8();
271 output.CacheVersion = 0;
273 if (sv.empty())
275 output.StringWidth = 0.f;
276 output.StringHeight = 0;
277 output.StringLine = 0;
279 return;
282 // resize fontSize if window not of 800x600.
283 if (keep800x600Ratio)
285 uint32 width, height;
286 driver->getWindowSize (width, height);
287 if ((height == 0) || (width == 0))
288 return;
289 // keep the 800*600 ratio
290 fontSize = (uint32)floor(fontSize*height/600.f);
291 fontSize = max(fontSize, (uint32)2);
294 sint32 penx = 0;
295 sint32 nMaxZ = -1000000, nMinZ = 1000000;
296 CMaterial *pMatFont = getFontMaterial();
297 CTextureFont *pTexFont = (CTextureFont*)(pMatFont->getTexture (0));
299 CTextureFont::SLetterKey k;
300 CTextureFont::SLetterInfo *pLI;
302 size_t idx = 0;
303 for (NLMISC::CUtfStringView::iterator it(sv.begin()), end(sv.end()); it != end && idx < len; ++it, ++idx)
305 // Creating font
306 k.Char = *it;
307 if (k.Char < 0x20)
308 k.Char += 0x2400;
309 k.FontGenerator = fontGen;
310 k.Size = fontSize;
311 k.Embolden = embolden;
312 k.Oblique = oblique;
313 pLI = pTexFont->getLetterInfo (k, false);
314 if(pLI != NULL)
316 if ((pLI->CharWidth > 0) && (pLI->CharHeight > 0))
318 // String info
319 sint32 nZ1 = (sint32)pLI->Top-(sint32)pLI->CharHeight;
320 sint32 nZ2 = pLI->Top;
322 if (nZ1 < nMinZ) nMinZ = nZ1;
323 if (nZ2 > nMaxZ) nMaxZ = nZ2;
325 penx += pLI->AdvX;
328 output.Length = idx;
329 nlassert(output.Length == std::min(len, NLMISC::CUtfStringView(output.Text).count()));
331 // compile string info
332 output.StringWidth = (float)penx;
333 if(nMaxZ>nMinZ)
335 output.StringHeight = (float)(nMaxZ - nMinZ);
336 output.StringLine = -(float)nMinZ;
338 else
340 output.StringHeight = 0;
341 output.StringLine = 0;
347 // ***************************************************************************
348 string CFontManager::getCacheInformation() const
350 string str;
351 str = "MaxMemory: " + NLMISC::toString(_MaxMemory) + " MemSize: " + NLMISC::toString(_MemSize) + " NbChar: " + NLMISC::toString(_NbChar);
352 return str;
355 // ***************************************************************************
356 void CFontManager::invalidate()
358 if (_TexFont)
359 _TexFont = NULL;
361 _TexFont = new CTextureFont;
362 _TexCacheNr++;
364 getFontMaterial()->setTexture(0, _TexFont);
369 } // NL3D