|
|
@@ -27,6 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
|
|
|
#pragma once
|
|
|
|
|
|
#include "Matrix4x4.h"
|
|
|
+#include "Quaternion.h"
|
|
|
#include "RendererTypes.h"
|
|
|
#include "StringUtils.h"
|
|
|
#include "Log.h"
|
|
|
@@ -39,6 +40,7 @@ struct Vector3;
|
|
|
struct Vector2;
|
|
|
struct Color4;
|
|
|
|
|
|
+//-------------------------------------------------------------------------
|
|
|
struct VertexData
|
|
|
{
|
|
|
float x;
|
|
|
@@ -47,12 +49,51 @@ struct VertexData
|
|
|
float v;
|
|
|
};
|
|
|
|
|
|
+//-------------------------------------------------------------------------
|
|
|
struct IndexData
|
|
|
{
|
|
|
uint16_t a;
|
|
|
uint16_t b;
|
|
|
};
|
|
|
|
|
|
+#define UTF8_ACCEPT 0
|
|
|
+
|
|
|
+//-------------------------------------------------------------------------
|
|
|
+static const uint8_t s_utf8d[364] =
|
|
|
+{
|
|
|
+ // The first part of the table maps bytes to character classes that
|
|
|
+ // to reduce the size of the transition table and create bitmasks.
|
|
|
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
|
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
|
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
|
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
|
|
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
|
|
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
|
|
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
|
|
+ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
|
|
|
+
|
|
|
+ // The second part is a transition table that maps a combination
|
|
|
+ // of a state of the automaton and a character class to a state.
|
|
|
+ 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
|
|
|
+ 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
|
|
|
+ 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
|
|
|
+ 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
|
|
|
+ 12,36,12,12,12,12,12,12,12,12,12,12
|
|
|
+};
|
|
|
+
|
|
|
+//-------------------------------------------------------------------------
|
|
|
+uint32_t utf8_decode(uint32_t* state, uint32_t* code_point, uint8_t character)
|
|
|
+{
|
|
|
+ uint32_t byte = character;
|
|
|
+ uint32_t type = s_utf8d[byte];
|
|
|
+
|
|
|
+ *code_point = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*code_point << 6) : (0xff >> type) & (byte);
|
|
|
+ *state = s_utf8d[256 + *state + type];
|
|
|
+
|
|
|
+ return *state;
|
|
|
+}
|
|
|
+
|
|
|
+//-------------------------------------------------------------------------
|
|
|
struct GuiText
|
|
|
{
|
|
|
//-------------------------------------------------------------------------
|
|
|
@@ -89,6 +130,7 @@ struct GuiText
|
|
|
material->bind(m_r, uniform);
|
|
|
|
|
|
const char* str = m_str.c_str();
|
|
|
+ const float scale = ((float)m_font_size / (float)m_resource->font_size());
|
|
|
|
|
|
TransientVertexBuffer vb;
|
|
|
TransientIndexBuffer ib;
|
|
|
@@ -97,61 +139,91 @@ struct GuiText
|
|
|
m_r.reserve_transient_index_buffer(&ib, 6 * string::strlen(str));
|
|
|
|
|
|
uint16_t index = 0;
|
|
|
- float advance = 0.0f;
|
|
|
+ float x_pen_advance = 0.0f;
|
|
|
+ float y_pen_advance = 0.0f;
|
|
|
+
|
|
|
+ uint32_t state = 0;
|
|
|
+ uint32_t code_point = 0;
|
|
|
for (uint32_t i = 0; i < string::strlen(str); i++)
|
|
|
{
|
|
|
- FontGlyphData g = m_resource->get_glyph(str[i]);
|
|
|
-
|
|
|
- const float x = (float) g.x / m_resource->size();
|
|
|
- const float y = (float) g.y / m_resource->size();
|
|
|
- const float width = (float) g.width / m_resource->size();
|
|
|
- const float height = (float) g.height / m_resource->size();
|
|
|
-
|
|
|
- const float u0 = x;
|
|
|
- const float v0 = y;
|
|
|
- const float u1 = x + width;
|
|
|
- const float v1 = y - height;
|
|
|
-
|
|
|
- (*(VertexData*)(vb.data)).x = m_pos.x + advance;
|
|
|
- (*(VertexData*)(vb.data)).y = m_pos.y;
|
|
|
- (*(VertexData*)(vb.data)).u = u0;
|
|
|
- (*(VertexData*)(vb.data)).v = v1;
|
|
|
- vb.data += sizeof(VertexData);
|
|
|
-
|
|
|
- (*(VertexData*)(vb.data)).x = m_pos.x + m_font_size + advance;
|
|
|
- (*(VertexData*)(vb.data)).y = m_pos.y;
|
|
|
- (*(VertexData*)(vb.data)).u = u1;
|
|
|
- (*(VertexData*)(vb.data)).v = v1;
|
|
|
- vb.data += sizeof(VertexData);
|
|
|
-
|
|
|
- (*(VertexData*)(vb.data)).x = m_pos.x + m_font_size + advance;
|
|
|
- (*(VertexData*)(vb.data)).y = m_pos.y - m_font_size;
|
|
|
- (*(VertexData*)(vb.data)).u = u1;
|
|
|
- (*(VertexData*)(vb.data)).v = v0;
|
|
|
- vb.data += sizeof(VertexData);
|
|
|
-
|
|
|
- (*(VertexData*)(vb.data)).x = m_pos.x + advance;
|
|
|
- (*(VertexData*)(vb.data)).y = m_pos.y - m_font_size;
|
|
|
- (*(VertexData*)(vb.data)).u = u0;
|
|
|
- (*(VertexData*)(vb.data)).v = v0;
|
|
|
- vb.data += sizeof(VertexData);
|
|
|
-
|
|
|
-
|
|
|
- (*(IndexData*)(ib.data)).a = index;
|
|
|
- (*(IndexData*)(ib.data)).b = index + 1;
|
|
|
- ib.data += sizeof(IndexData);
|
|
|
-
|
|
|
- (*(IndexData*)(ib.data)).a = index + 2;
|
|
|
- (*(IndexData*)(ib.data)).b = index;
|
|
|
- ib.data += sizeof(IndexData);
|
|
|
-
|
|
|
- (*(IndexData*)(ib.data)).a = index + 2;
|
|
|
- (*(IndexData*)(ib.data)).b = index + 3;
|
|
|
- ib.data += sizeof(IndexData);
|
|
|
-
|
|
|
- index += 4;
|
|
|
-
|
|
|
- advance += g.x_advance;
|
|
|
+ switch (str[i])
|
|
|
+ {
|
|
|
+ case '\n':
|
|
|
+ {
|
|
|
+ x_pen_advance = 0.0f;
|
|
|
+ y_pen_advance += m_resource->font_size();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ case '\t':
|
|
|
+ {
|
|
|
+ x_pen_advance += m_font_size * 4;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (utf8_decode(&state, &code_point, str[i]) == UTF8_ACCEPT)
|
|
|
+ {
|
|
|
+ FontGlyphData g = m_resource->get_glyph(code_point);
|
|
|
+
|
|
|
+ // Set pen position
|
|
|
+ m_pen.x = m_pos.x + g.x_offset;
|
|
|
+ m_pen.y = m_pos.y + (g.height - g.y_offset);
|
|
|
+
|
|
|
+ // Position coords
|
|
|
+ const float x0 = (m_pen.x + x_pen_advance) * scale;
|
|
|
+ const float y0 = (m_pen.y + y_pen_advance) * scale;
|
|
|
+ const float x1 = (m_pen.x + g.width + x_pen_advance) * scale;
|
|
|
+ const float y1 = (m_pen.y - g.height + y_pen_advance) * scale;
|
|
|
+
|
|
|
+ // Texture coords
|
|
|
+ const float u0 = (float) g.x / m_resource->texture_size();
|
|
|
+ const float v0 = (float) g.y / m_resource->texture_size();
|
|
|
+ const float u1 = u0 + ((float) g.width) / m_resource->texture_size();
|
|
|
+ const float v1 = v0 - ((float) g.height) / m_resource->texture_size();
|
|
|
+
|
|
|
+ // Fill vertex buffer
|
|
|
+ (*(VertexData*)(vb.data)).x = x0;
|
|
|
+ (*(VertexData*)(vb.data)).y = y0;
|
|
|
+ (*(VertexData*)(vb.data)).u = u0;
|
|
|
+ (*(VertexData*)(vb.data)).v = v1;
|
|
|
+ vb.data += sizeof(VertexData);
|
|
|
+
|
|
|
+ (*(VertexData*)(vb.data)).x = x1;
|
|
|
+ (*(VertexData*)(vb.data)).y = y0;
|
|
|
+ (*(VertexData*)(vb.data)).u = u1;
|
|
|
+ (*(VertexData*)(vb.data)).v = v1;
|
|
|
+ vb.data += sizeof(VertexData);
|
|
|
+
|
|
|
+ (*(VertexData*)(vb.data)).x = x1;
|
|
|
+ (*(VertexData*)(vb.data)).y = y1;
|
|
|
+ (*(VertexData*)(vb.data)).u = u1;
|
|
|
+ (*(VertexData*)(vb.data)).v = v0;
|
|
|
+ vb.data += sizeof(VertexData);
|
|
|
+
|
|
|
+ (*(VertexData*)(vb.data)).x = x0;
|
|
|
+ (*(VertexData*)(vb.data)).y = y1;
|
|
|
+ (*(VertexData*)(vb.data)).u = u0;
|
|
|
+ (*(VertexData*)(vb.data)).v = v0;
|
|
|
+ vb.data += sizeof(VertexData);
|
|
|
+
|
|
|
+ // Fill index buffer
|
|
|
+ (*(IndexData*)(ib.data)).a = index;
|
|
|
+ (*(IndexData*)(ib.data)).b = index + 1;
|
|
|
+ ib.data += sizeof(IndexData);
|
|
|
+
|
|
|
+ (*(IndexData*)(ib.data)).a = index + 2;
|
|
|
+ (*(IndexData*)(ib.data)).b = index;
|
|
|
+ ib.data += sizeof(IndexData);
|
|
|
+
|
|
|
+ (*(IndexData*)(ib.data)).a = index + 2;
|
|
|
+ (*(IndexData*)(ib.data)).b = index + 3;
|
|
|
+ ib.data += sizeof(IndexData);
|
|
|
+
|
|
|
+ // Advance pen position
|
|
|
+ x_pen_advance += g.x_advance;
|
|
|
+
|
|
|
+ index += 4;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
m_r.set_vertex_buffer(vb);
|
|
|
@@ -167,7 +239,10 @@ public:
|
|
|
|
|
|
DynamicString m_str;
|
|
|
uint32_t m_font_size;
|
|
|
+
|
|
|
+ // position states
|
|
|
Vector3 m_pos;
|
|
|
+ Vector2 m_pen;
|
|
|
|
|
|
MaterialId m_material;
|
|
|
};
|