OpenBarnyard
 
Loading...
Searching...
No Matches
AGUI2Font.cpp
Go to the documentation of this file.
1#include "pch.h"
2#include "AGUI2Font.h"
3#include "AGUI2.h"
4
5#include <cwctype>
6
7//-----------------------------------------------------------------------------
8// Enables memory debugging.
9// Note: Should be the last include!
10//-----------------------------------------------------------------------------
11#include <Core/TMemoryDebugOn.h>
12
14{
15 TASSERT( a_pFontDef->uiNumMaterials != 0 );
16
17 m_pFontDef = a_pFontDef;
18 m_ppMaterials = new AGUI2Material*[ a_pFontDef->uiNumMaterials ];
19
20 auto pRenderer = AGUI2::GetRenderer();
21 auto pTextureName = a_pFontDef->szTextureNames;
22
23 for ( TUINT8 i = 0; i < a_pFontDef->uiNumMaterials; i++ )
24 {
25 m_ppMaterials[ i ] = pRenderer->CreateMaterial( pTextureName );
26
27 while ( *pTextureName != '\0' ) pTextureName++;
28 pTextureName++;
29 }
30
31 return TTRUE;
32}
33
34void AGUI2Font::DrawTextWrapped( const TWCHAR* a_wszText, TFLOAT a_fX, TFLOAT a_fY, TFLOAT a_fWidth, TFLOAT a_fHeight, TUINT32 a_uiColour, TFLOAT a_fScale, TextAlign a_eAlign, void* a_fnCallback /*= TNULL*/ )
35{
36 auto pFontDef = m_pFontDef;
37
38 if ( a_wszText && a_wszText[ 0 ] != '\0' && pFontDef )
39 {
40 auto pTextBuffer = a_wszText;
41
42 do
43 {
44 auto pTextBuffer2 = pTextBuffer;
45
46 while ( *pTextBuffer2 != L'\0' && std::iswspace( *pTextBuffer2 ) != 0 )
47 {
48 if ( *pTextBuffer2 == L'\n' ) break;
49 pTextBuffer2++;
50 }
51
52 auto wChar = *pTextBuffer2;
53
54 if ( wChar == L'\n' )
55 {
56 pTextBuffer = pTextBuffer2 + 1;
57 }
58 else
59 {
60 if ( wChar == L'\0' ) return;
61
62 pTextBuffer = TNULL;
63 TFLOAT fWidth1 = 0.0f;
64 TFLOAT fWidth2 = 0.0f;
65 auto pTextBuffer3 = pTextBuffer2;
66
67 do {
68 if ( pFontDef->ui16MinCharacter <= wChar && ( wChar <= pFontDef->ui16MaxCharacter ) )
69 {
70 TINT iCharIndex = pFontDef->pCharactersMap[ wChar - pFontDef->ui16MinCharacter ];
71
72 if ( iCharIndex >= 0 )
73 {
74 auto& pCharData = pFontDef->pCharactersData[ iCharIndex ];
75 fWidth1 += ( pFontDef->iLetterSpacing + pCharData.iRightPadding + pCharData.iLeftPadding + pCharData.ui8CharWidth ) * a_fScale;
76 }
77 }
78
79 if ( wChar == L'\n' )
80 {
81 fWidth2 = fWidth1;
82 pTextBuffer = pTextBuffer3;
83 break;
84 }
85
86 if ( std::iswspace( wChar ) != 0 && *pTextBuffer3 != L'\xA0' )
87 {
88 fWidth2 = fWidth1;
89 pTextBuffer = pTextBuffer3;
90 }
91
92 wChar = pTextBuffer3[ 1 ];
93 if ( wChar == L'\0' ) break;
94 pTextBuffer3++;
95
96 } while ( fWidth1 < a_fWidth || pTextBuffer == TNULL );
97
98 if ( pTextBuffer3[ 1 ] == L'\0' )
99 {
100 pTextBuffer = pTextBuffer3 + 1;
101 fWidth2 = fWidth1;
102 }
103
104 TFLOAT fPosX;
105
106 if ( a_eAlign == TextAlign_Left )
107 fPosX = a_fX;
108 else if ( a_eAlign == TextAlign_Center )
109 fPosX = ( a_fWidth - fWidth2 ) * 0.5f + a_fX;
110 else if ( a_eAlign == TextAlign_Right )
111 fPosX = ( a_fWidth - fWidth2 ) + a_fX;
112 else
113 fPosX = a_fX;
114
115 DrawTextSingleLine( pTextBuffer2, pTextBuffer - pTextBuffer2, fPosX, a_fY, a_uiColour, a_fScale, a_fnCallback );
116 }
117
118 a_fY += ( pFontDef->uiLineHeight + pFontDef->uiLinesMargin ) * a_fScale;
119
120 } while ( *pTextBuffer != L'\0' );
121 }
122}
123
124void AGUI2Font::DrawTextSingleLine( const TWCHAR* a_wszText, TINT a_iTextLength, TFLOAT a_fX, TFLOAT a_fY, TUINT32 a_uiColour, TFLOAT a_fScale, void* a_fnCallback /*= TNULL*/ )
125{
126 auto pRenderer = AGUI2::GetRenderer();
127 pRenderer->SetColour( a_uiColour );
128
129 TFLOAT fOffsetX = 0.0f;
130 TFLOAT fOffsetY = 0.0f;
131 TFLOAT fXToUV = 0.0f;
132 TFLOAT fYToUV = 0.0f;
133 AGUI2Material* pPrevMaterial = TNULL;
134
135 for ( TINT i = 0; i < a_iTextLength; i++ )
136 {
137 auto pFontDef = m_pFontDef;
138 auto wChar = a_wszText[ i ];
139
140 if ( pFontDef->ui16MinCharacter <= wChar && wChar <= pFontDef->ui16MaxCharacter )
141 {
142 TINT iCharIndex = pFontDef->pCharactersMap[ wChar - pFontDef->ui16MinCharacter ];
143
144 if ( iCharIndex >= 0 )
145 {
146 auto& pCharData = pFontDef->pCharactersData[ iCharIndex ];
147 TFLOAT fPos1X = pCharData.iLeftPadding * a_fScale + a_fX;
148
149 if ( pCharData.ui8CharWidth != 0 && pCharData.ui8CharHeight != 0 )
150 {
151 AGUI2Material* pMaterial = ( pFontDef->uiNumMaterials > 1 ) ?
152 m_ppMaterials[ ( wChar >> 8 ) ] :
153 m_ppMaterials[ 0 ];
154
155 if ( pMaterial != pPrevMaterial )
156 {
157 pPrevMaterial = pMaterial;
158 pRenderer->SetMaterial( pMaterial );
159 fXToUV = 1.0f / pRenderer->GetWidth( pMaterial );
160 fYToUV = 1.0f / pRenderer->GetHeight( pMaterial );
161 }
162
163 TFIXME( "Call a_fnCallback(i, fOffsetX, fOffsetY)" );
164
165 TFLOAT fPos1Y = ( ( pFontDef->uiLineHeight + pCharData.Unk5 ) - pCharData.ui8CharHeight ) * a_fScale + a_fY;
166 TFLOAT fPos2Y = fPos1Y + ( pCharData.ui8CharHeight + 1 ) * a_fScale;
167 TFLOAT fPos2X = fPos1X + ( pCharData.ui8CharWidth + 1 ) * a_fScale;
168
169 pRenderer->RenderRectangle(
170 { fPos1X + fOffsetX, fPos1Y + fOffsetY },
171 { fPos2X + fOffsetX, fPos2Y + fOffsetY },
172 { ( pCharData.ui16PosX ) * fXToUV, ( pCharData.ui16PosY ) * fYToUV },
173 { ( pCharData.ui16PosX + pCharData.ui8CharWidth + 1 ) * fXToUV, ( pCharData.ui16PosY + pCharData.ui8CharHeight + 1 ) * fYToUV }
174 );
175 }
176
177 TFLOAT fPos2X = TFLOAT( pFontDef->iLetterSpacing + pCharData.iRightPadding + pCharData.ui8CharWidth );
178 a_fX = fPos2X * a_fScale + fPos1X;
179 }
180 }
181 }
182}
183
184TFLOAT AGUI2Font::GetTextHeightWrapped( const TWCHAR* a_wszText, TFLOAT a_fMaxWidth, TFLOAT a_fScale )
185{
186 auto pFontDef = m_pFontDef;
187
188 if ( a_wszText && a_wszText[ 0 ] != '\0' && pFontDef )
189 {
190 TFLOAT fHeight = 0.0f;
191 auto pTextBuffer = a_wszText;
192
193 do
194 {
195 auto pTextBuffer2 = pTextBuffer;
196
197 while ( *pTextBuffer2 != L'\0' && std::iswspace( *pTextBuffer2 ) != 0 )
198 {
199 if ( *pTextBuffer2 == L'\n' ) break;
200 pTextBuffer2++;
201 }
202
203 auto wChar = *pTextBuffer2;
204
205 if ( wChar == L'\n' )
206 {
207 pTextBuffer = pTextBuffer2 + 1;
208 }
209 else
210 {
211 if ( wChar == L'\0' ) break;
212
213 pTextBuffer = TNULL;
214 TFLOAT fWidth1 = 0.0f;
215 TFLOAT fWidth2 = 0.0f;
216 auto pTextBuffer3 = pTextBuffer2;
217
218 do {
219 if ( pFontDef->ui16MinCharacter <= wChar && ( wChar <= pFontDef->ui16MaxCharacter ) )
220 {
221 TINT iCharIndex = pFontDef->pCharactersMap[ wChar - pFontDef->ui16MinCharacter ];
222
223 if ( iCharIndex >= 0 )
224 {
225 auto& pCharData = pFontDef->pCharactersData[ iCharIndex ];
226 fWidth1 += ( pFontDef->iLetterSpacing + pCharData.iRightPadding + pCharData.iLeftPadding + pCharData.ui8CharWidth ) * a_fScale;
227 }
228 }
229
230 if ( wChar == L'\n' )
231 {
232 fWidth2 = fWidth1;
233 pTextBuffer = pTextBuffer3;
234 break;
235 }
236
237 if ( std::iswspace( wChar ) != 0 && *pTextBuffer3 != L'\xA0' )
238 {
239 fWidth2 = fWidth1;
240 pTextBuffer = pTextBuffer3;
241 }
242
243 wChar = pTextBuffer3[ 1 ];
244 if ( wChar == L'\0' ) break;
245 pTextBuffer3++;
246
247 } while ( fWidth1 < a_fMaxWidth || pTextBuffer == TNULL );
248
249 if ( pTextBuffer3[ 1 ] == L'\0' )
250 {
251 pTextBuffer = pTextBuffer3 + 1;
252 fWidth2 = fWidth1;
253 }
254 }
255
256 fHeight += ( pFontDef->uiLineHeight + pFontDef->uiLinesMargin ) * a_fScale;
257
258 } while ( *pTextBuffer != L'\0' );
259
260 return fHeight;
261 }
262 else
263 {
264 return 0.0f;
265 }
266}
267
268TFLOAT AGUI2Font::GetTextWidth( const TWCHAR* a_wszText, TFLOAT a_fScale )
269{
270 if ( a_wszText && m_pFontDef )
271 {
272 return GetTextWidth(
273 a_wszText,
274 Toshi::TStringManager::String16Length( a_wszText ),
275 a_fScale
276 );
277 }
278
279 return 0.0f;
280}
281
282TFLOAT AGUI2Font::GetTextWidth( const TWCHAR* a_wszText, TINT a_iTextLength, TFLOAT a_fScale )
283{
284 TINT iWidth = 0;
285
286 for ( TINT i = 0; i < a_iTextLength; i++ )
287 {
288 auto pFontDef = m_pFontDef;
289 auto wChar = a_wszText[ i ];
290
291 if ( pFontDef->ui16MinCharacter <= wChar && wChar <= pFontDef->ui16MaxCharacter )
292 {
293 TINT iCharIndex = pFontDef->pCharactersMap[ wChar - pFontDef->ui16MinCharacter ];
294
295 if ( iCharIndex >= 0 )
296 {
297 auto& pCharData = pFontDef->pCharactersData[ iCharIndex ];
298 iWidth += pFontDef->iLetterSpacing + pCharData.iRightPadding + pCharData.iLeftPadding + pCharData.ui8CharWidth;
299 }
300 }
301 }
302
303 return iWidth * a_fScale;
304}
305
307{
308 if ( m_pFontDef )
309 return TFLOAT( m_pFontDef->uiLinesMargin );
310
311 return 0.0f;
312}
#define TASSERT(X,...)
Definition Defines.h:138
#define TFIXME(DESC)
Definition Defines.h:135
wchar_t TWCHAR
Definition Typedefs.h:21
uint8_t TUINT8
Definition Typedefs.h:17
float TFLOAT
Definition Typedefs.h:4
#define TNULL
Definition Typedefs.h:23
uint32_t TUINT32
Definition Typedefs.h:13
int TINT
Definition Typedefs.h:7
#define TTRUE
Definition Typedefs.h:25
bool TBOOL
Definition Typedefs.h:6
static AGUI2Renderer * GetRenderer()
Definition AGUI2.cpp:239
TUINT8 uiNumMaterials
Definition AGUI2Font.h:26
const TCHAR * szTextureNames
Definition AGUI2Font.h:22
TBOOL Create(AGUI2FontDef *a_pFontDef)
Definition AGUI2Font.cpp:13
void DrawTextWrapped(const TWCHAR *a_wszText, TFLOAT a_fX, TFLOAT a_fY, TFLOAT a_fWidth, TFLOAT a_fHeight, TUINT32 a_uiColour, TFLOAT a_fScale, TextAlign a_eAlign, void *a_fnCallback=nullptr)
Definition AGUI2Font.cpp:34
TFLOAT GetTextHeightWrapped(const TWCHAR *a_wszText, TFLOAT a_fMaxWidth, TFLOAT a_fScale=1.0f)
TFLOAT GetTextWidth(const TWCHAR *a_wszText, TFLOAT a_fScale=1.0f)
@ TextAlign_Center
Definition AGUI2Font.h:40
@ TextAlign_Right
Definition AGUI2Font.h:41
@ TextAlign_Left
Definition AGUI2Font.h:39
void DrawTextSingleLine(const TWCHAR *a_wszText, TINT a_iTextLength, TFLOAT a_fX, TFLOAT a_fY, TUINT32 a_uiColour, TFLOAT a_fScale, void *a_fnCallback=nullptr)
TFLOAT GetLinesMargin()