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.
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