1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010-2021 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
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"
46 // ***************************************************************************
47 CMaterial
* CFontManager::getFontMaterial()
51 _TexFont
= new CTextureFont
;
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
);
69 // ***************************************************************************
70 void CFontManager::computeString (NLMISC::CUtfStringView sv
,
71 CFontGenerator
*fontGen
,
72 const NLMISC::CRGBA
&color
,
77 CComputedString
&output
,
78 bool keep800x600Ratio
)
82 // resize fontSize if window not of 800x600.
86 driver
->getWindowSize (width
, height
);
87 if ((height
== 0) || (width
== 0))
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
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
;
121 output
.XMin
= FLT_MAX
;
122 output
.XMax
= -FLT_MAX
;
123 output
.ZMin
= FLT_MAX
;
124 output
.ZMax
= -FLT_MAX
;
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();
138 CVertexBufferReadWrite vba
;
139 output
.Vertices
.lock (vba
);
145 for (NLMISC::CUtfStringView::iterator
it(sv
.begin()), end(sv
.end()); it
!= end
; ++it
, ++idx
)
152 if (k
.Char
< 0x20) // Control Characters
154 if (k
.Char
== 0x7F) // DEL
156 k
.FontGenerator
= fontGen
;
158 k
.Embolden
= embolden
;
161 CTextureFont::SLetterInfo
*pLI
= pTexFont
->getLetterInfo (k
, true);
166 // If letter is heavily upscaled, then there is noticeable clipping on edges
167 // fixing UV will make it bit better
168 if ((pLI
->Size
>> 1) > pLI
->glyph
->Size
)
170 hlfPixTexW
= 0.5f
* TexRatioW
;
171 hlfPixTexH
= 0.5f
* TexRatioH
;
176 dz
= -((sint32
)pLI
->CharHeight
- (sint32
)(pLI
->Top
));
178 x1
= (penx
+ dx
) - hlfPixScrW
;
179 z1
= (penz
+ dz
) - hlfPixScrH
;
180 x2
= (penx
+ dx
+ (sint32
)pLI
->CharWidth
) + hlfPixScrW
;
181 z2
= (penz
+ dz
+ (sint32
)pLI
->CharHeight
) + hlfPixScrH
;
183 vba
.setVertexCoord (j
, x1
, 0, z1
);
184 vba
.setTexCoord (j
, 0, pLI
->glyph
->U0
-hlfPixTexW
, pLI
->glyph
->V1
+hlfPixTexH
);
187 vba
.setVertexCoord (j
, x2
, 0, z1
);
188 vba
.setTexCoord (j
, 0, pLI
->glyph
->U1
+hlfPixTexW
, pLI
->glyph
->V1
+hlfPixTexH
);
191 vba
.setVertexCoord (j
, x2
, 0, z2
);
192 vba
.setTexCoord (j
, 0, pLI
->glyph
->U1
+hlfPixTexW
, pLI
->glyph
->V0
-hlfPixTexH
);
195 vba
.setVertexCoord (j
, x1
, 0, z2
);
196 vba
.setTexCoord (j
, 0, pLI
->glyph
->U0
-hlfPixTexW
, pLI
->glyph
->V0
-hlfPixTexH
);
200 output
.XMin
= min(output
.XMin
, x1
);
201 output
.XMin
= min(output
.XMin
, x2
);
202 output
.XMax
= max(output
.XMax
, x1
);
203 output
.XMax
= max(output
.XMax
, x2
);
204 output
.ZMin
= min(output
.ZMin
, z1
);
205 output
.ZMin
= min(output
.ZMin
, z2
);
206 output
.ZMax
= max(output
.ZMax
, z1
);
207 output
.ZMax
= max(output
.ZMax
, z2
);
210 sint32 nZ1
= (sint32
)pLI
->Top
-(sint32
)pLI
->CharHeight
;
211 sint32 nZ2
= pLI
->Top
;
213 if (nZ1
< nMinZ
) nMinZ
= nZ1
;
214 if (nZ2
> nMaxZ
) nMaxZ
= nZ2
;
220 output
.Material
= pMatFont
;
223 output
.Vertices
.setNumVertices (j
);
225 nlassert(output
.Length
== NLMISC::CUtfStringView(output
.Text
).count());
227 // compile string info
228 output
.StringWidth
= (float)penx
;
231 output
.StringHeight
= (float)(nMaxZ
- nMinZ
);
232 output
.StringLine
= -(float)nMinZ
;
236 output
.StringHeight
= 0;
237 output
.StringLine
= 0;
242 // ***************************************************************************
243 void CFontManager::computeStringInfo ( NLMISC::CUtfStringView sv
,
244 CFontGenerator
*fontGen
,
245 const NLMISC::CRGBA
&color
,
250 CComputedString
&output
,
251 bool keep800x600Ratio
)
253 computeStringInfo(sv
, sv
.largestSize(), fontGen
, color
, fontSize
, embolden
, oblique
, driver
, output
, keep800x600Ratio
);
257 // ***************************************************************************
258 void CFontManager::computeStringInfo ( NLMISC::CUtfStringView sv
,
260 CFontGenerator
*fontGen
,
261 const NLMISC::CRGBA
&color
,
266 CComputedString
&output
,
267 bool keep800x600Ratio
)
269 output
.Color
= color
;
271 // save string info for later rebuild as needed
272 if (sv
.ptr() != output
.Text
.c_str()) // don't resave if rebuilding
273 output
.Text
= sv
.toUtf8();
274 output
.CacheVersion
= 0;
278 output
.StringWidth
= 0.f
;
279 output
.StringHeight
= 0;
280 output
.StringLine
= 0;
285 // resize fontSize if window not of 800x600.
286 if (keep800x600Ratio
)
288 uint32 width
, height
;
289 driver
->getWindowSize (width
, height
);
290 if ((height
== 0) || (width
== 0))
292 // keep the 800*600 ratio
293 fontSize
= (uint32
)floor(fontSize
*height
/600.f
);
294 fontSize
= max(fontSize
, (uint32
)2);
298 sint32 nMaxZ
= -1000000, nMinZ
= 1000000;
299 CMaterial
*pMatFont
= getFontMaterial();
300 CTextureFont
*pTexFont
= (CTextureFont
*)(pMatFont
->getTexture (0));
302 CTextureFont::SLetterKey k
;
303 CTextureFont::SLetterInfo
*pLI
;
306 for (NLMISC::CUtfStringView::iterator
it(sv
.begin()), end(sv
.end()); it
!= end
&& idx
< len
; ++it
, ++idx
)
315 k
.FontGenerator
= fontGen
;
317 k
.Embolden
= embolden
;
319 pLI
= pTexFont
->getLetterInfo (k
, false);
322 if ((pLI
->CharWidth
> 0) && (pLI
->CharHeight
> 0))
325 sint32 nZ1
= (sint32
)pLI
->Top
-(sint32
)pLI
->CharHeight
;
326 sint32 nZ2
= pLI
->Top
;
328 if (nZ1
< nMinZ
) nMinZ
= nZ1
;
329 if (nZ2
> nMaxZ
) nMaxZ
= nZ2
;
335 nlassert(output
.Length
== std::min(len
, NLMISC::CUtfStringView(output
.Text
).count()));
337 // compile string info
338 output
.StringWidth
= (float)penx
;
341 output
.StringHeight
= (float)(nMaxZ
- nMinZ
);
342 output
.StringLine
= -(float)nMinZ
;
346 output
.StringHeight
= 0;
347 output
.StringLine
= 0;
353 // ***************************************************************************
354 string
CFontManager::getCacheInformation() const
357 str
= "MaxMemory: " + NLMISC::toString(_MaxMemory
) + " MemSize: " + NLMISC::toString(_MemSize
) + " NbChar: " + NLMISC::toString(_NbChar
);
361 // ***************************************************************************
362 void CFontManager::invalidate()
367 _TexFont
= new CTextureFont
;
370 getFontMaterial()->setTexture(0, _TexFont
);