LiteRGSS 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/LiteRGSS/Bitmap.cpp +316 -0
- data/ext/LiteRGSS/Bitmap.h +24 -0
- data/ext/LiteRGSS/BlendMode.cpp +202 -0
- data/ext/LiteRGSS/BlendMode.h +20 -0
- data/ext/LiteRGSS/CBitmap_Element.cpp +50 -0
- data/ext/LiteRGSS/CBitmap_Element.h +17 -0
- data/ext/LiteRGSS/CDrawable_Element.cpp +38 -0
- data/ext/LiteRGSS/CDrawable_Element.h +30 -0
- data/ext/LiteRGSS/CRect_Element.h +15 -0
- data/ext/LiteRGSS/CShaderSprite_Element.cpp +17 -0
- data/ext/LiteRGSS/CShaderSprite_Element.h +17 -0
- data/ext/LiteRGSS/CSprite_Element.cpp +15 -0
- data/ext/LiteRGSS/CSprite_Element.h +36 -0
- data/ext/LiteRGSS/CText_Element.cpp +12 -0
- data/ext/LiteRGSS/CText_Element.h +29 -0
- data/ext/LiteRGSS/CTone_Element.h +17 -0
- data/ext/LiteRGSS/CViewport_Element.cpp +224 -0
- data/ext/LiteRGSS/CViewport_Element.h +57 -0
- data/ext/LiteRGSS/Color.cpp +200 -0
- data/ext/LiteRGSS/Color.h +22 -0
- data/ext/LiteRGSS/Fonts.cpp +126 -0
- data/ext/LiteRGSS/Fonts.h +20 -0
- data/ext/LiteRGSS/Graphics.cpp +314 -0
- data/ext/LiteRGSS/Graphics.h +31 -0
- data/ext/LiteRGSS/Graphics.local.cpp +365 -0
- data/ext/LiteRGSS/Graphics.local.h +37 -0
- data/ext/LiteRGSS/Image.cpp +460 -0
- data/ext/LiteRGSS/Image.h +32 -0
- data/ext/LiteRGSS/Input.cpp +664 -0
- data/ext/LiteRGSS/Input.h +38 -0
- data/ext/LiteRGSS/LiteRGSS.cpp +34 -0
- data/ext/LiteRGSS/LiteRGSS.h +113 -0
- data/ext/LiteRGSS/Rect.cpp +324 -0
- data/ext/LiteRGSS/Rect.h +24 -0
- data/ext/LiteRGSS/Shader.cpp +279 -0
- data/ext/LiteRGSS/Shader.h +13 -0
- data/ext/LiteRGSS/ShaderSprite.cpp +78 -0
- data/ext/LiteRGSS/ShaderSprite.h +8 -0
- data/ext/LiteRGSS/Sprite.cpp +495 -0
- data/ext/LiteRGSS/Sprite.h +43 -0
- data/ext/LiteRGSS/Table.cpp +228 -0
- data/ext/LiteRGSS/Table.h +29 -0
- data/ext/LiteRGSS/Table32.cpp +228 -0
- data/ext/LiteRGSS/Table32.h +29 -0
- data/ext/LiteRGSS/Text.cpp +574 -0
- data/ext/LiteRGSS/Text.h +52 -0
- data/ext/LiteRGSS/Texture.hpp +735 -0
- data/ext/LiteRGSS/Tone.cpp +228 -0
- data/ext/LiteRGSS/Tone.h +22 -0
- data/ext/LiteRGSS/Viewport.cpp +491 -0
- data/ext/LiteRGSS/Viewport.h +33 -0
- data/ext/LiteRGSS/Yuki.cpp +29 -0
- data/ext/LiteRGSS/Yuki.h +8 -0
- data/ext/LiteRGSS/Yuki_Gif.cpp +218 -0
- data/ext/LiteRGSS/Yuki_Gif.h +25 -0
- data/ext/LiteRGSS/extconf.rb +8 -0
- data/ext/LiteRGSS/libnsgif.c +1169 -0
- data/ext/LiteRGSS/libnsgif.h +183 -0
- data/ext/LiteRGSS/libnsgif.hpp +184 -0
- data/ext/LiteRGSS/lodepng.cpp +6245 -0
- data/ext/LiteRGSS/lodepng.h +1769 -0
- data/ext/LiteRGSS/lzw.c +377 -0
- data/ext/LiteRGSS/lzw.h +105 -0
- data/ext/LiteRGSS/sf_Text2.cpp +690 -0
- data/ext/LiteRGSS/sf_Text2.hpp +549 -0
- data/ext/LiteRGSS/utils/log.h +21 -0
- metadata +112 -0
@@ -0,0 +1,690 @@
|
|
1
|
+
////////////////////////////////////////////////////////////
|
2
|
+
//
|
3
|
+
// SFML - Simple and Fast Multimedia Library
|
4
|
+
// Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
|
5
|
+
//
|
6
|
+
// This software is provided 'as-is', without any express or implied warranty.
|
7
|
+
// In no event will the authors be held liable for any damages arising from the use of this software.
|
8
|
+
//
|
9
|
+
// Permission is granted to anyone to use this software for any purpose,
|
10
|
+
// including commercial applications, and to alter it and redistribute it freely,
|
11
|
+
// subject to the following restrictions:
|
12
|
+
//
|
13
|
+
// 1. The origin of this software must not be misrepresented;
|
14
|
+
// you must not claim that you wrote the original software.
|
15
|
+
// If you use this software in a product, an acknowledgment
|
16
|
+
// in the product documentation would be appreciated but is not required.
|
17
|
+
//
|
18
|
+
// 2. Altered source versions must be plainly marked as such,
|
19
|
+
// and must not be misrepresented as being the original software.
|
20
|
+
//
|
21
|
+
// 3. This notice may not be removed or altered from any source distribution.
|
22
|
+
//
|
23
|
+
////////////////////////////////////////////////////////////
|
24
|
+
|
25
|
+
////////////////////////////////////////////////////////////
|
26
|
+
// Headers
|
27
|
+
////////////////////////////////////////////////////////////
|
28
|
+
#include "LiteRGSS.h"
|
29
|
+
#include "sf_Text2.hpp"
|
30
|
+
#include <SFML/Graphics/Texture.hpp>
|
31
|
+
#include <SFML/Graphics/RenderTarget.hpp>
|
32
|
+
#include <cmath>
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
namespace
|
37
|
+
{
|
38
|
+
// Add an underline or strikethrough line to the vertex array
|
39
|
+
void addLine(sf::VertexArray& vertices, float lineLength, float lineTop, const sf::Color& color, float offset, float thickness, float outlineThickness = 0)
|
40
|
+
{
|
41
|
+
float top = std::floor(lineTop + offset - (thickness / 2) + 0.5f);
|
42
|
+
float bottom = top + std::floor(thickness + 0.5f);
|
43
|
+
|
44
|
+
vertices.append(sf::Vertex(sf::Vector2f(-outlineThickness, top - outlineThickness), color, sf::Vector2f(1, 1)));
|
45
|
+
vertices.append(sf::Vertex(sf::Vector2f(lineLength + outlineThickness, top - outlineThickness), color, sf::Vector2f(1, 1)));
|
46
|
+
vertices.append(sf::Vertex(sf::Vector2f(-outlineThickness, bottom + outlineThickness), color, sf::Vector2f(1, 1)));
|
47
|
+
vertices.append(sf::Vertex(sf::Vector2f(-outlineThickness, bottom + outlineThickness), color, sf::Vector2f(1, 1)));
|
48
|
+
vertices.append(sf::Vertex(sf::Vector2f(lineLength + outlineThickness, top - outlineThickness), color, sf::Vector2f(1, 1)));
|
49
|
+
vertices.append(sf::Vertex(sf::Vector2f(lineLength + outlineThickness, bottom + outlineThickness), color, sf::Vector2f(1, 1)));
|
50
|
+
}
|
51
|
+
|
52
|
+
// Add a glyph quad to the vertex array
|
53
|
+
void addGlyphQuad(sf::VertexArray& vertices, sf::Vector2f position, const sf::Color& color, const sf::Glyph& glyph, float italicShear, float outlineThickness = 0)
|
54
|
+
{
|
55
|
+
float left = glyph.bounds.left;
|
56
|
+
float top = glyph.bounds.top;
|
57
|
+
float right = glyph.bounds.left + glyph.bounds.width;
|
58
|
+
float bottom = glyph.bounds.top + glyph.bounds.height;
|
59
|
+
|
60
|
+
float u1 = static_cast<float>(glyph.textureRect.left);
|
61
|
+
float v1 = static_cast<float>(glyph.textureRect.top);
|
62
|
+
float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width);
|
63
|
+
float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height);
|
64
|
+
|
65
|
+
vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u1, v1)));
|
66
|
+
vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1)));
|
67
|
+
vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2)));
|
68
|
+
vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u1, v2)));
|
69
|
+
vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1)));
|
70
|
+
vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * bottom - outlineThickness, position.y + bottom - outlineThickness), color, sf::Vector2f(u2, v2)));
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
|
75
|
+
namespace sf
|
76
|
+
{
|
77
|
+
////////////////////////////////////////////////////////////
|
78
|
+
Text2::Text2() :
|
79
|
+
m_string(),
|
80
|
+
m_font(NULL),
|
81
|
+
m_characterSize(30),
|
82
|
+
m_letterSpacingFactor(1.f),
|
83
|
+
m_lineSpacingFactor(1.f),
|
84
|
+
m_style(Regular),
|
85
|
+
m_fillColor(255, 255, 255),
|
86
|
+
m_outlineColor(0, 0, 0),
|
87
|
+
m_outlineThickness(0),
|
88
|
+
m_vertices(Triangles),
|
89
|
+
m_outlineVertices(Triangles),
|
90
|
+
m_bounds(),
|
91
|
+
m_geometryNeedUpdate(false),
|
92
|
+
m_fontTextureId(0),
|
93
|
+
m_DrawShadow(true),
|
94
|
+
m_numberCharsToDraw(0xFFFFFFFF),
|
95
|
+
m_lineHeight(16.0f)
|
96
|
+
{
|
97
|
+
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
////////////////////////////////////////////////////////////
|
102
|
+
Text2::Text2(const String& string, const Font& font, unsigned int characterSize) :
|
103
|
+
m_string(string),
|
104
|
+
m_font(&font),
|
105
|
+
m_characterSize(characterSize),
|
106
|
+
m_letterSpacingFactor(1.f),
|
107
|
+
m_lineSpacingFactor(1.f),
|
108
|
+
m_style(Regular),
|
109
|
+
m_fillColor(255, 255, 255),
|
110
|
+
m_outlineColor(0, 0, 0),
|
111
|
+
m_outlineThickness(0),
|
112
|
+
m_vertices(Triangles),
|
113
|
+
m_outlineVertices(Triangles),
|
114
|
+
m_bounds(),
|
115
|
+
m_geometryNeedUpdate(true),
|
116
|
+
m_fontTextureId(0),
|
117
|
+
m_DrawShadow(true),
|
118
|
+
m_numberCharsToDraw(0xFFFFFFFF),
|
119
|
+
m_lineHeight(16.0f)
|
120
|
+
{
|
121
|
+
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
////////////////////////////////////////////////////////////
|
126
|
+
void Text2::setString(const String& string)
|
127
|
+
{
|
128
|
+
if (m_string != string)
|
129
|
+
{
|
130
|
+
m_string = string;
|
131
|
+
m_geometryNeedUpdate = true;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
|
136
|
+
////////////////////////////////////////////////////////////
|
137
|
+
void Text2::setFont(const Font& font)
|
138
|
+
{
|
139
|
+
if (m_font != &font)
|
140
|
+
{
|
141
|
+
m_font = &font;
|
142
|
+
m_geometryNeedUpdate = true;
|
143
|
+
//<< YuriAdd
|
144
|
+
if (m_font != nullptr && !SmoothScreen)
|
145
|
+
const_cast<sf::Texture*>(&m_font->getTexture(m_characterSize))->setSmooth(false);
|
146
|
+
//>> YuriAdd
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
////////////////////////////////////////////////////////////
|
152
|
+
void Text2::setCharacterSize(unsigned int size)
|
153
|
+
{
|
154
|
+
if (m_characterSize != size)
|
155
|
+
{
|
156
|
+
m_characterSize = size;
|
157
|
+
m_geometryNeedUpdate = true;
|
158
|
+
//<< YuriAdd
|
159
|
+
if (m_font != nullptr && !SmoothScreen)
|
160
|
+
const_cast<sf::Texture*>(&m_font->getTexture(m_characterSize))->setSmooth(false);
|
161
|
+
//<< YuriAdd
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
////////////////////////////////////////////////////////////
|
167
|
+
void Text2::setLetterSpacing(float spacingFactor)
|
168
|
+
{
|
169
|
+
if (m_letterSpacingFactor != spacingFactor)
|
170
|
+
{
|
171
|
+
m_letterSpacingFactor = spacingFactor;
|
172
|
+
m_geometryNeedUpdate = true;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
|
177
|
+
////////////////////////////////////////////////////////////
|
178
|
+
void Text2::setLineSpacing(float spacingFactor)
|
179
|
+
{
|
180
|
+
if (m_lineSpacingFactor != spacingFactor)
|
181
|
+
{
|
182
|
+
m_lineSpacingFactor = spacingFactor;
|
183
|
+
m_geometryNeedUpdate = true;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
////////////////////////////////////////////////////////////
|
189
|
+
void Text2::setStyle(Uint32 style)
|
190
|
+
{
|
191
|
+
if (m_style != style)
|
192
|
+
{
|
193
|
+
m_style = style;
|
194
|
+
m_geometryNeedUpdate = true;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
|
199
|
+
////////////////////////////////////////////////////////////
|
200
|
+
void Text2::setColor(const Color& color)
|
201
|
+
{
|
202
|
+
setFillColor(color);
|
203
|
+
}
|
204
|
+
|
205
|
+
|
206
|
+
////////////////////////////////////////////////////////////
|
207
|
+
void Text2::setFillColor(const Color& color)
|
208
|
+
{
|
209
|
+
if (color != m_fillColor)
|
210
|
+
{
|
211
|
+
m_fillColor = color;
|
212
|
+
|
213
|
+
// Change vertex colors directly, no need to update whole geometry
|
214
|
+
// (if geometry is updated anyway, we can skip this step)
|
215
|
+
if (!m_geometryNeedUpdate)
|
216
|
+
{
|
217
|
+
for (std::size_t i = 0; i < m_vertices.getVertexCount(); ++i)
|
218
|
+
m_vertices[i].color = m_fillColor;
|
219
|
+
}
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
|
224
|
+
////////////////////////////////////////////////////////////
|
225
|
+
void Text2::setOutlineColor(const Color& color)
|
226
|
+
{
|
227
|
+
if (color != m_outlineColor)
|
228
|
+
{
|
229
|
+
m_outlineColor = color;
|
230
|
+
|
231
|
+
// Change vertex colors directly, no need to update whole geometry
|
232
|
+
// (if geometry is updated anyway, we can skip this step)
|
233
|
+
if (!m_geometryNeedUpdate)
|
234
|
+
{
|
235
|
+
for (std::size_t i = 0; i < m_outlineVertices.getVertexCount(); ++i)
|
236
|
+
m_outlineVertices[i].color = m_outlineColor;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
|
242
|
+
////////////////////////////////////////////////////////////
|
243
|
+
void Text2::setOutlineThickness(float thickness)
|
244
|
+
{
|
245
|
+
if (thickness != m_outlineThickness)
|
246
|
+
{
|
247
|
+
m_outlineThickness = thickness;
|
248
|
+
m_DrawShadow = (thickness < 1.0f);
|
249
|
+
m_geometryNeedUpdate = true;
|
250
|
+
}
|
251
|
+
}
|
252
|
+
|
253
|
+
|
254
|
+
////////////////////////////////////////////////////////////
|
255
|
+
const String& Text2::getString() const
|
256
|
+
{
|
257
|
+
return m_string;
|
258
|
+
}
|
259
|
+
|
260
|
+
|
261
|
+
////////////////////////////////////////////////////////////
|
262
|
+
const Font* Text2::getFont() const
|
263
|
+
{
|
264
|
+
return m_font;
|
265
|
+
}
|
266
|
+
|
267
|
+
|
268
|
+
////////////////////////////////////////////////////////////
|
269
|
+
unsigned int Text2::getCharacterSize() const
|
270
|
+
{
|
271
|
+
return m_characterSize;
|
272
|
+
}
|
273
|
+
|
274
|
+
|
275
|
+
////////////////////////////////////////////////////////////
|
276
|
+
float Text2::getLetterSpacing() const
|
277
|
+
{
|
278
|
+
return m_letterSpacingFactor;
|
279
|
+
}
|
280
|
+
|
281
|
+
|
282
|
+
////////////////////////////////////////////////////////////
|
283
|
+
float Text2::getLineSpacing() const
|
284
|
+
{
|
285
|
+
return m_lineSpacingFactor;
|
286
|
+
}
|
287
|
+
|
288
|
+
|
289
|
+
////////////////////////////////////////////////////////////
|
290
|
+
Uint32 Text2::getStyle() const
|
291
|
+
{
|
292
|
+
return m_style;
|
293
|
+
}
|
294
|
+
|
295
|
+
|
296
|
+
////////////////////////////////////////////////////////////
|
297
|
+
const Color& Text2::getColor() const
|
298
|
+
{
|
299
|
+
return getFillColor();
|
300
|
+
}
|
301
|
+
|
302
|
+
|
303
|
+
////////////////////////////////////////////////////////////
|
304
|
+
const Color& Text2::getFillColor() const
|
305
|
+
{
|
306
|
+
return m_fillColor;
|
307
|
+
}
|
308
|
+
|
309
|
+
|
310
|
+
////////////////////////////////////////////////////////////
|
311
|
+
const Color& Text2::getOutlineColor() const
|
312
|
+
{
|
313
|
+
return m_outlineColor;
|
314
|
+
}
|
315
|
+
|
316
|
+
|
317
|
+
////////////////////////////////////////////////////////////
|
318
|
+
float Text2::getOutlineThickness() const
|
319
|
+
{
|
320
|
+
return m_outlineThickness;
|
321
|
+
}
|
322
|
+
|
323
|
+
|
324
|
+
////////////////////////////////////////////////////////////
|
325
|
+
Vector2f Text2::findCharacterPos(std::size_t index) const
|
326
|
+
{
|
327
|
+
// Make sure that we have a valid font
|
328
|
+
if (!m_font)
|
329
|
+
return Vector2f();
|
330
|
+
|
331
|
+
// Adjust the index if it's out of range
|
332
|
+
if (index > m_string.getSize())
|
333
|
+
index = m_string.getSize();
|
334
|
+
|
335
|
+
// Precompute the variables needed by the algorithm
|
336
|
+
bool isBold = m_style & Bold;
|
337
|
+
float whitespaceWidth = m_font->getGlyph(L' ', m_characterSize, isBold).advance;
|
338
|
+
float letterSpacing = (whitespaceWidth / 3.f) * (m_letterSpacingFactor - 1.f);
|
339
|
+
whitespaceWidth += letterSpacing;
|
340
|
+
float lineSpacing = m_lineHeight * m_lineSpacingFactor;//m_font->getLineSpacing(m_characterSize) * m_lineSpacingFactor;
|
341
|
+
|
342
|
+
// Compute the position
|
343
|
+
Vector2f position;
|
344
|
+
Uint32 prevChar = 0;
|
345
|
+
for (std::size_t i = 0; i < index; ++i)
|
346
|
+
{
|
347
|
+
Uint32 curChar = m_string[i];
|
348
|
+
|
349
|
+
// Apply the kerning offset
|
350
|
+
position.x += m_font->getKerning(prevChar, curChar, m_characterSize);
|
351
|
+
prevChar = curChar;
|
352
|
+
|
353
|
+
// Handle special characters
|
354
|
+
switch (curChar)
|
355
|
+
{
|
356
|
+
case ' ': position.x += whitespaceWidth; continue;
|
357
|
+
case '\t': position.x += whitespaceWidth * 4; continue;
|
358
|
+
case '\n': position.y += lineSpacing; position.x = 0; continue;
|
359
|
+
}
|
360
|
+
|
361
|
+
// For regular characters, add the advance offset of the glyph
|
362
|
+
position.x += m_font->getGlyph(curChar, m_characterSize, isBold).advance + letterSpacing;
|
363
|
+
}
|
364
|
+
|
365
|
+
// Transform the position to global coordinates
|
366
|
+
position = getTransform().transformPoint(position);
|
367
|
+
|
368
|
+
return position;
|
369
|
+
}
|
370
|
+
|
371
|
+
|
372
|
+
////////////////////////////////////////////////////////////
|
373
|
+
FloatRect Text2::getLocalBounds() const
|
374
|
+
{
|
375
|
+
ensureGeometryUpdate();
|
376
|
+
|
377
|
+
return m_bounds;
|
378
|
+
}
|
379
|
+
|
380
|
+
|
381
|
+
////////////////////////////////////////////////////////////
|
382
|
+
FloatRect Text2::getGlobalBounds() const
|
383
|
+
{
|
384
|
+
return getTransform().transformRect(getLocalBounds());
|
385
|
+
}
|
386
|
+
|
387
|
+
|
388
|
+
////////////////////////////////////////////////////////////
|
389
|
+
void Text2::draw(RenderTarget& target, RenderStates states) const
|
390
|
+
{
|
391
|
+
if (m_font)
|
392
|
+
{
|
393
|
+
ensureGeometryUpdate();
|
394
|
+
|
395
|
+
states.transform *= getTransform();
|
396
|
+
states.texture = &m_font->getTexture(m_characterSize);
|
397
|
+
|
398
|
+
// Only draw the outline if there is something to draw
|
399
|
+
if (m_outlineThickness != 0 || m_DrawShadow)
|
400
|
+
target.draw(m_outlineVertices, states);
|
401
|
+
|
402
|
+
target.draw(m_vertices, states);
|
403
|
+
}
|
404
|
+
}
|
405
|
+
|
406
|
+
///////////
|
407
|
+
Uint32 Text2::getTextWidth(const String& string) const
|
408
|
+
{
|
409
|
+
// No font or Text2: nothing to draw
|
410
|
+
if (!m_font || string.isEmpty())
|
411
|
+
return 0;
|
412
|
+
|
413
|
+
// Compute values related to the text style
|
414
|
+
bool isBold = m_style & Bold;
|
415
|
+
float italicShear = (m_style & Italic) ? 0.209f : 0.f; // 12 degrees in radians
|
416
|
+
|
417
|
+
// Compute the location of the strike through dynamically
|
418
|
+
// We use the center point of the lowercase 'x' glyph as the reference
|
419
|
+
// We reuse the underline thickness as the thickness of the strike through as well
|
420
|
+
FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, isBold).bounds;
|
421
|
+
float strikeThroughOffset = xBounds.top + xBounds.height / 2.f;
|
422
|
+
|
423
|
+
// Precompute the variables needed by the algorithm
|
424
|
+
float whitespaceWidth = m_font->getGlyph(L' ', m_characterSize, isBold).advance;
|
425
|
+
float letterSpacing = (whitespaceWidth / 3.f) * (m_letterSpacingFactor - 1.f);
|
426
|
+
whitespaceWidth += letterSpacing;
|
427
|
+
float lineSpacing = m_lineHeight * m_lineSpacingFactor;//m_font->getLineSpacing(m_characterSize) * m_lineSpacingFactor;
|
428
|
+
float x = 0.f;
|
429
|
+
float y = static_cast<float>(m_characterSize);
|
430
|
+
|
431
|
+
// Create one quad for each character
|
432
|
+
float minX = static_cast<float>(m_characterSize);
|
433
|
+
float minY = static_cast<float>(m_characterSize);
|
434
|
+
float maxX = 0.f;
|
435
|
+
float maxY = 0.f;
|
436
|
+
Uint32 prevChar = 0;
|
437
|
+
for (std::size_t i = 0; i < string.getSize(); ++i)
|
438
|
+
{
|
439
|
+
Uint32 curChar = string[i];
|
440
|
+
|
441
|
+
// Apply the kerning offset
|
442
|
+
x += m_font->getKerning(prevChar, curChar, m_characterSize);
|
443
|
+
prevChar = curChar;
|
444
|
+
|
445
|
+
// Handle special characters
|
446
|
+
if ((curChar == L' ') || (curChar == L'\n') || (curChar == L'\t'))
|
447
|
+
{
|
448
|
+
// Update the current bounds (min coordinates)
|
449
|
+
minX = std::min(minX, x);
|
450
|
+
minY = std::min(minY, y);
|
451
|
+
|
452
|
+
switch (curChar)
|
453
|
+
{
|
454
|
+
case L' ': x += whitespaceWidth; break;
|
455
|
+
case L'\t': x += whitespaceWidth * 4; break;
|
456
|
+
case L'\n': y += lineSpacing; x = 0; break;
|
457
|
+
}
|
458
|
+
|
459
|
+
// Update the current bounds (max coordinates)
|
460
|
+
maxX = std::max(maxX, x);
|
461
|
+
maxY = std::max(maxY, y);
|
462
|
+
|
463
|
+
// Next glyph, no need to create a quad for whitespace
|
464
|
+
continue;
|
465
|
+
}
|
466
|
+
|
467
|
+
if (m_outlineThickness != 0 && !m_DrawShadow)
|
468
|
+
{
|
469
|
+
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, isBold, m_outlineThickness);
|
470
|
+
|
471
|
+
float left = glyph.bounds.left;
|
472
|
+
float top = glyph.bounds.top;
|
473
|
+
float right = glyph.bounds.left + glyph.bounds.width;
|
474
|
+
float bottom = glyph.bounds.top + glyph.bounds.height;
|
475
|
+
|
476
|
+
// Update the current bounds with the outlined glyph bounds
|
477
|
+
minX = std::min(minX, x + left - italicShear * bottom - m_outlineThickness);
|
478
|
+
maxX = std::max(maxX, x + right - italicShear * top - m_outlineThickness);
|
479
|
+
minY = std::min(minY, y + top - m_outlineThickness);
|
480
|
+
maxY = std::max(maxY, y + bottom - m_outlineThickness);
|
481
|
+
}
|
482
|
+
|
483
|
+
// Extract the current glyph's description
|
484
|
+
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, isBold);
|
485
|
+
|
486
|
+
// Update the current bounds with the non outlined glyph bounds
|
487
|
+
if (m_DrawShadow || m_outlineThickness == 0)
|
488
|
+
{
|
489
|
+
float left = glyph.bounds.left;
|
490
|
+
float top = glyph.bounds.top;
|
491
|
+
float right = glyph.bounds.left + glyph.bounds.width;
|
492
|
+
float bottom = glyph.bounds.top + glyph.bounds.height;
|
493
|
+
|
494
|
+
minX = std::min(minX, x + left - italicShear * bottom);
|
495
|
+
maxX = std::max(maxX, x + right - italicShear * top);
|
496
|
+
minY = std::min(minY, y + top);
|
497
|
+
maxY = std::max(maxY, y + bottom);
|
498
|
+
}
|
499
|
+
|
500
|
+
// Advance to the next character
|
501
|
+
x += glyph.advance + letterSpacing;
|
502
|
+
}
|
503
|
+
|
504
|
+
// Add 1 if drawing shadow
|
505
|
+
if (m_DrawShadow)
|
506
|
+
maxX += 1.f;
|
507
|
+
|
508
|
+
return static_cast<Uint32>(maxX);
|
509
|
+
}
|
510
|
+
|
511
|
+
////////////////////////////////////////////////////////////
|
512
|
+
void Text2::ensureGeometryUpdate() const
|
513
|
+
{
|
514
|
+
if (!m_font)
|
515
|
+
return;
|
516
|
+
|
517
|
+
// Do nothing, if geometry has not changed and the font texture has not changed
|
518
|
+
if (!m_geometryNeedUpdate && m_font->getTexture(m_characterSize).m_cacheId == m_fontTextureId)
|
519
|
+
return;
|
520
|
+
|
521
|
+
// Save the current fonts texture id
|
522
|
+
m_fontTextureId = m_font->getTexture(m_characterSize).m_cacheId;
|
523
|
+
|
524
|
+
// Mark geometry as updated
|
525
|
+
m_geometryNeedUpdate = false;
|
526
|
+
|
527
|
+
// Clear the previous geometry
|
528
|
+
m_vertices.clear();
|
529
|
+
m_outlineVertices.clear();
|
530
|
+
m_bounds = FloatRect();
|
531
|
+
|
532
|
+
// No text: nothing to draw
|
533
|
+
if (m_string.isEmpty())
|
534
|
+
return;
|
535
|
+
|
536
|
+
// Compute values related to the text style
|
537
|
+
bool isBold = m_style & Bold;
|
538
|
+
bool isUnderlined = m_style & Underlined;
|
539
|
+
bool isStrikeThrough = m_style & StrikeThrough;
|
540
|
+
float italicShear = (m_style & Italic) ? 0.209f : 0.f; // 12 degrees in radians
|
541
|
+
float underlineOffset = m_font->getUnderlinePosition(m_characterSize);
|
542
|
+
float underlineThickness = m_font->getUnderlineThickness(m_characterSize);
|
543
|
+
|
544
|
+
// Compute the location of the strike through dynamically
|
545
|
+
// We use the center point of the lowercase 'x' glyph as the reference
|
546
|
+
// We reuse the underline thickness as the thickness of the strike through as well
|
547
|
+
FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, isBold).bounds;
|
548
|
+
float strikeThroughOffset = xBounds.top + xBounds.height / 2.f;
|
549
|
+
|
550
|
+
// Precompute the variables needed by the algorithm
|
551
|
+
float whitespaceWidth = m_font->getGlyph(L' ', m_characterSize, isBold).advance;
|
552
|
+
float letterSpacing = (whitespaceWidth / 3.f) * (m_letterSpacingFactor - 1.f);
|
553
|
+
whitespaceWidth += letterSpacing;
|
554
|
+
float lineSpacing = m_lineHeight * m_lineSpacingFactor;//m_font->getLineSpacing(m_characterSize) * m_lineSpacingFactor;
|
555
|
+
float x = 0.f;
|
556
|
+
float y = static_cast<float>(m_characterSize);
|
557
|
+
|
558
|
+
// Create one quad for each character
|
559
|
+
float minX = static_cast<float>(m_characterSize);
|
560
|
+
float minY = static_cast<float>(m_characterSize);
|
561
|
+
float maxX = 0.f;
|
562
|
+
float maxY = 0.f;
|
563
|
+
Uint32 prevChar = 0;
|
564
|
+
for (std::size_t i = 0; i < m_string.getSize() && i < m_numberCharsToDraw; ++i)
|
565
|
+
{
|
566
|
+
Uint32 curChar = m_string[i];
|
567
|
+
|
568
|
+
// Apply the kerning offset
|
569
|
+
x += m_font->getKerning(prevChar, curChar, m_characterSize);
|
570
|
+
prevChar = curChar;
|
571
|
+
|
572
|
+
// If we're using the underlined style and there's a new line, draw a line
|
573
|
+
if (isUnderlined && (curChar == L'\n'))
|
574
|
+
{
|
575
|
+
addLine(m_vertices, x, y, m_fillColor, underlineOffset, underlineThickness);
|
576
|
+
|
577
|
+
if (m_outlineThickness != 0)
|
578
|
+
addLine(m_outlineVertices, x, y, m_outlineColor, underlineOffset, underlineThickness, m_outlineThickness);
|
579
|
+
}
|
580
|
+
|
581
|
+
// If we're using the strike through style and there's a new line, draw a line across all characters
|
582
|
+
if (isStrikeThrough && (curChar == L'\n'))
|
583
|
+
{
|
584
|
+
addLine(m_vertices, x, y, m_fillColor, strikeThroughOffset, underlineThickness);
|
585
|
+
|
586
|
+
if (m_outlineThickness != 0)
|
587
|
+
addLine(m_outlineVertices, x, y, m_outlineColor, strikeThroughOffset, underlineThickness, m_outlineThickness);
|
588
|
+
}
|
589
|
+
|
590
|
+
// Handle special characters
|
591
|
+
if ((curChar == L' ') || (curChar == L'\n') || (curChar == L'\t'))
|
592
|
+
{
|
593
|
+
// Update the current bounds (min coordinates)
|
594
|
+
minX = std::min(minX, x);
|
595
|
+
minY = std::min(minY, y);
|
596
|
+
|
597
|
+
switch (curChar)
|
598
|
+
{
|
599
|
+
case L' ': x += whitespaceWidth; break;
|
600
|
+
case L'\t': x += whitespaceWidth * 4; break;
|
601
|
+
case L'\n': y += lineSpacing; x = 0; break;
|
602
|
+
}
|
603
|
+
|
604
|
+
// Update the current bounds (max coordinates)
|
605
|
+
maxX = std::max(maxX, x);
|
606
|
+
maxY = std::max(maxY, y);
|
607
|
+
|
608
|
+
// Next glyph, no need to create a quad for whitespace
|
609
|
+
continue;
|
610
|
+
}
|
611
|
+
|
612
|
+
// Apply the Shadow
|
613
|
+
if (m_DrawShadow)
|
614
|
+
{
|
615
|
+
// Extract the current glyph's description
|
616
|
+
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, isBold);
|
617
|
+
addGlyphQuad(m_outlineVertices, Vector2f(x + 1, y), m_outlineColor, glyph, italicShear);
|
618
|
+
addGlyphQuad(m_outlineVertices, Vector2f(x + 1, y + 1), m_outlineColor, glyph, italicShear);
|
619
|
+
addGlyphQuad(m_outlineVertices, Vector2f(x, y + 1), m_outlineColor, glyph, italicShear);
|
620
|
+
}
|
621
|
+
// Apply the outline
|
622
|
+
else if (m_outlineThickness != 0)
|
623
|
+
{
|
624
|
+
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, isBold, m_outlineThickness);
|
625
|
+
|
626
|
+
float left = glyph.bounds.left;
|
627
|
+
float top = glyph.bounds.top;
|
628
|
+
float right = glyph.bounds.left + glyph.bounds.width;
|
629
|
+
float bottom = glyph.bounds.top + glyph.bounds.height;
|
630
|
+
|
631
|
+
// Add the outline glyph to the vertices
|
632
|
+
addGlyphQuad(m_outlineVertices, Vector2f(x, y), m_outlineColor, glyph, italicShear, m_outlineThickness);
|
633
|
+
|
634
|
+
// Update the current bounds with the outlined glyph bounds
|
635
|
+
minX = std::min(minX, x + left - italicShear * bottom - m_outlineThickness);
|
636
|
+
maxX = std::max(maxX, x + right - italicShear * top - m_outlineThickness);
|
637
|
+
minY = std::min(minY, y + top - m_outlineThickness);
|
638
|
+
maxY = std::max(maxY, y + bottom - m_outlineThickness);
|
639
|
+
}
|
640
|
+
|
641
|
+
// Extract the current glyph's description
|
642
|
+
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, isBold);
|
643
|
+
|
644
|
+
// Add the glyph to the vertices
|
645
|
+
addGlyphQuad(m_vertices, Vector2f(x, y), m_fillColor, glyph, italicShear);
|
646
|
+
|
647
|
+
// Update the current bounds with the non outlined glyph bounds
|
648
|
+
if (m_DrawShadow || m_outlineThickness == 0)
|
649
|
+
{
|
650
|
+
float left = glyph.bounds.left;
|
651
|
+
float top = glyph.bounds.top;
|
652
|
+
float right = glyph.bounds.left + glyph.bounds.width;
|
653
|
+
float bottom = glyph.bounds.top + glyph.bounds.height;
|
654
|
+
|
655
|
+
minX = std::min(minX, x + left - italicShear * bottom);
|
656
|
+
maxX = std::max(maxX, x + right - italicShear * top);
|
657
|
+
minY = std::min(minY, y + top);
|
658
|
+
maxY = std::max(maxY, y + bottom);
|
659
|
+
}
|
660
|
+
|
661
|
+
// Advance to the next character
|
662
|
+
x += glyph.advance + letterSpacing;
|
663
|
+
}
|
664
|
+
|
665
|
+
// If we're using the underlined style, add the last line
|
666
|
+
if (isUnderlined && (x > 0))
|
667
|
+
{
|
668
|
+
addLine(m_vertices, x, y, m_fillColor, underlineOffset, underlineThickness);
|
669
|
+
|
670
|
+
if (m_outlineThickness != 0)
|
671
|
+
addLine(m_outlineVertices, x, y, m_outlineColor, underlineOffset, underlineThickness, m_outlineThickness);
|
672
|
+
}
|
673
|
+
|
674
|
+
// If we're using the strike through style, add the last line across all characters
|
675
|
+
if (isStrikeThrough && (x > 0))
|
676
|
+
{
|
677
|
+
addLine(m_vertices, x, y, m_fillColor, strikeThroughOffset, underlineThickness);
|
678
|
+
|
679
|
+
if (m_outlineThickness != 0)
|
680
|
+
addLine(m_outlineVertices, x, y, m_outlineColor, strikeThroughOffset, underlineThickness, m_outlineThickness);
|
681
|
+
}
|
682
|
+
|
683
|
+
// Update the bounding rectangle
|
684
|
+
m_bounds.left = minX;
|
685
|
+
m_bounds.top = minY;
|
686
|
+
m_bounds.width = maxX - minX;
|
687
|
+
m_bounds.height = maxY - minY;
|
688
|
+
}
|
689
|
+
|
690
|
+
} // namespace sf
|