LiteRGSS 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/ext/LiteRGSS/Bitmap.cpp +316 -0
  3. data/ext/LiteRGSS/Bitmap.h +24 -0
  4. data/ext/LiteRGSS/BlendMode.cpp +202 -0
  5. data/ext/LiteRGSS/BlendMode.h +20 -0
  6. data/ext/LiteRGSS/CBitmap_Element.cpp +50 -0
  7. data/ext/LiteRGSS/CBitmap_Element.h +17 -0
  8. data/ext/LiteRGSS/CDrawable_Element.cpp +38 -0
  9. data/ext/LiteRGSS/CDrawable_Element.h +30 -0
  10. data/ext/LiteRGSS/CRect_Element.h +15 -0
  11. data/ext/LiteRGSS/CShaderSprite_Element.cpp +17 -0
  12. data/ext/LiteRGSS/CShaderSprite_Element.h +17 -0
  13. data/ext/LiteRGSS/CSprite_Element.cpp +15 -0
  14. data/ext/LiteRGSS/CSprite_Element.h +36 -0
  15. data/ext/LiteRGSS/CText_Element.cpp +12 -0
  16. data/ext/LiteRGSS/CText_Element.h +29 -0
  17. data/ext/LiteRGSS/CTone_Element.h +17 -0
  18. data/ext/LiteRGSS/CViewport_Element.cpp +224 -0
  19. data/ext/LiteRGSS/CViewport_Element.h +57 -0
  20. data/ext/LiteRGSS/Color.cpp +200 -0
  21. data/ext/LiteRGSS/Color.h +22 -0
  22. data/ext/LiteRGSS/Fonts.cpp +126 -0
  23. data/ext/LiteRGSS/Fonts.h +20 -0
  24. data/ext/LiteRGSS/Graphics.cpp +314 -0
  25. data/ext/LiteRGSS/Graphics.h +31 -0
  26. data/ext/LiteRGSS/Graphics.local.cpp +365 -0
  27. data/ext/LiteRGSS/Graphics.local.h +37 -0
  28. data/ext/LiteRGSS/Image.cpp +460 -0
  29. data/ext/LiteRGSS/Image.h +32 -0
  30. data/ext/LiteRGSS/Input.cpp +664 -0
  31. data/ext/LiteRGSS/Input.h +38 -0
  32. data/ext/LiteRGSS/LiteRGSS.cpp +34 -0
  33. data/ext/LiteRGSS/LiteRGSS.h +113 -0
  34. data/ext/LiteRGSS/Rect.cpp +324 -0
  35. data/ext/LiteRGSS/Rect.h +24 -0
  36. data/ext/LiteRGSS/Shader.cpp +279 -0
  37. data/ext/LiteRGSS/Shader.h +13 -0
  38. data/ext/LiteRGSS/ShaderSprite.cpp +78 -0
  39. data/ext/LiteRGSS/ShaderSprite.h +8 -0
  40. data/ext/LiteRGSS/Sprite.cpp +495 -0
  41. data/ext/LiteRGSS/Sprite.h +43 -0
  42. data/ext/LiteRGSS/Table.cpp +228 -0
  43. data/ext/LiteRGSS/Table.h +29 -0
  44. data/ext/LiteRGSS/Table32.cpp +228 -0
  45. data/ext/LiteRGSS/Table32.h +29 -0
  46. data/ext/LiteRGSS/Text.cpp +574 -0
  47. data/ext/LiteRGSS/Text.h +52 -0
  48. data/ext/LiteRGSS/Texture.hpp +735 -0
  49. data/ext/LiteRGSS/Tone.cpp +228 -0
  50. data/ext/LiteRGSS/Tone.h +22 -0
  51. data/ext/LiteRGSS/Viewport.cpp +491 -0
  52. data/ext/LiteRGSS/Viewport.h +33 -0
  53. data/ext/LiteRGSS/Yuki.cpp +29 -0
  54. data/ext/LiteRGSS/Yuki.h +8 -0
  55. data/ext/LiteRGSS/Yuki_Gif.cpp +218 -0
  56. data/ext/LiteRGSS/Yuki_Gif.h +25 -0
  57. data/ext/LiteRGSS/extconf.rb +8 -0
  58. data/ext/LiteRGSS/libnsgif.c +1169 -0
  59. data/ext/LiteRGSS/libnsgif.h +183 -0
  60. data/ext/LiteRGSS/libnsgif.hpp +184 -0
  61. data/ext/LiteRGSS/lodepng.cpp +6245 -0
  62. data/ext/LiteRGSS/lodepng.h +1769 -0
  63. data/ext/LiteRGSS/lzw.c +377 -0
  64. data/ext/LiteRGSS/lzw.h +105 -0
  65. data/ext/LiteRGSS/sf_Text2.cpp +690 -0
  66. data/ext/LiteRGSS/sf_Text2.hpp +549 -0
  67. data/ext/LiteRGSS/utils/log.h +21 -0
  68. 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