1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 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
)
149 if (k
.Char
< 0x20) // Control Characters
151 if (k
.Char
== 0x7F) // DEL
153 k
.FontGenerator
= fontGen
;
155 k
.Embolden
= embolden
;
158 CTextureFont::SLetterInfo
*pLI
= pTexFont
->getLetterInfo (k
, true);
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
;
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
);
184 vba
.setVertexCoord (j
, x2
, 0, z1
);
185 vba
.setTexCoord (j
, 0, pLI
->glyph
->U1
+hlfPixTexW
, pLI
->glyph
->V1
+hlfPixTexH
);
188 vba
.setVertexCoord (j
, x2
, 0, z2
);
189 vba
.setTexCoord (j
, 0, pLI
->glyph
->U1
+hlfPixTexW
, pLI
->glyph
->V0
-hlfPixTexH
);
192 vba
.setVertexCoord (j
, x1
, 0, z2
);
193 vba
.setTexCoord (j
, 0, pLI
->glyph
->U0
-hlfPixTexW
, pLI
->glyph
->V0
-hlfPixTexH
);
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
);
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
;
217 output
.Material
= pMatFont
;
220 output
.Vertices
.setNumVertices (j
);
222 nlassert(output
.Length
== NLMISC::CUtfStringView(output
.Text
).count());
224 // compile string info
225 output
.StringWidth
= (float)penx
;
228 output
.StringHeight
= (float)(nMaxZ
- nMinZ
);
229 output
.StringLine
= -(float)nMinZ
;
233 output
.StringHeight
= 0;
234 output
.StringLine
= 0;
239 // ***************************************************************************
240 void CFontManager::computeStringInfo ( NLMISC::CUtfStringView sv
,
241 CFontGenerator
*fontGen
,
242 const NLMISC::CRGBA
&color
,
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
,
257 CFontGenerator
*fontGen
,
258 const NLMISC::CRGBA
&color
,
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;
275 output
.StringWidth
= 0.f
;
276 output
.StringHeight
= 0;
277 output
.StringLine
= 0;
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))
289 // keep the 800*600 ratio
290 fontSize
= (uint32
)floor(fontSize
*height
/600.f
);
291 fontSize
= max(fontSize
, (uint32
)2);
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
;
303 for (NLMISC::CUtfStringView::iterator
it(sv
.begin()), end(sv
.end()); it
!= end
&& idx
< len
; ++it
, ++idx
)
309 k
.FontGenerator
= fontGen
;
311 k
.Embolden
= embolden
;
313 pLI
= pTexFont
->getLetterInfo (k
, false);
316 if ((pLI
->CharWidth
> 0) && (pLI
->CharHeight
> 0))
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
;
329 nlassert(output
.Length
== std::min(len
, NLMISC::CUtfStringView(output
.Text
).count()));
331 // compile string info
332 output
.StringWidth
= (float)penx
;
335 output
.StringHeight
= (float)(nMaxZ
- nMinZ
);
336 output
.StringLine
= -(float)nMinZ
;
340 output
.StringHeight
= 0;
341 output
.StringLine
= 0;
347 // ***************************************************************************
348 string
CFontManager::getCacheInformation() const
351 str
= "MaxMemory: " + NLMISC::toString(_MaxMemory
) + " MemSize: " + NLMISC::toString(_MemSize
) + " NbChar: " + NLMISC::toString(_NbChar
);
355 // ***************************************************************************
356 void CFontManager::invalidate()
361 _TexFont
= new CTextureFont
;
364 getFontMaterial()->setTexture(0, _TexFont
);