LiteRGSS 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|