461 lines
14 KiB
C++
461 lines
14 KiB
C++
#include <cstdint>
|
|
#include <cmath>
|
|
#include <cassert>
|
|
#include "utils/logger.h"
|
|
#include "render/ui.h"
|
|
#include "render/vertexbuffer.h"
|
|
#include "render/indexbuffer.h"
|
|
#include "render/renderdevice.h"
|
|
#include "render/shadersystem.h"
|
|
#include "render/texturesmanager.h"
|
|
#include "render/texture2d.h"
|
|
|
|
struct DrawInfo
|
|
{
|
|
uint16_t vxcount;
|
|
uint16_t idxcount;
|
|
};
|
|
|
|
struct UIGlobals {
|
|
VertexBuffer* vb;
|
|
IndexBuffer* ib;
|
|
Shader* shader;
|
|
Texture2D* activetexture = nullptr;
|
|
Texture2D* defaultTexture = nullptr;
|
|
|
|
UIVertex* vertices = nullptr;
|
|
uint16_t* indices = nullptr;
|
|
DrawInfo drawInfo[MAX_UI_VERTICES];
|
|
uint16_t count = 0;
|
|
uint16_t position = 0;
|
|
uint16_t Indexposition = 0;
|
|
uint16_t currentIdx = 0;
|
|
} g_ui;
|
|
|
|
|
|
void uiInit()
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Buffer and context state
|
|
|
|
// Buffer creation
|
|
g_ui.vb = g_renderDevice->CreateVertexBuffer(nullptr, MAX_UI_VERTICES, true);
|
|
g_ui.ib = g_renderDevice->CreateIndexBuffer(nullptr, MAX_UI_INDICES, true);
|
|
|
|
// Create shader
|
|
|
|
InputLayoutDesc_t inputLayout[] =
|
|
{
|
|
{ VERTEXATTR_VEC2, SHADERSEMANTIC_POSITION },
|
|
{ VERTEXATTR_VEC2, SHADERSEMANTIC_TEXCOORD },
|
|
{ VERTEXATTR_VEC4, SHADERSEMANTIC_COLOR },
|
|
};
|
|
|
|
g_ui.shader = g_shaderSystem->CreateShader("ui", "content/shaders/ui_base.vs", "content/shaders/ui_tex.ps", inputLayout, sizeof(inputLayout) / sizeof(inputLayout[0]));
|
|
g_ui.shader->m_stride = sizeof( UIVertex );
|
|
|
|
g_ui.defaultTexture = g_texturesManager->LoadTexture2D("$white$");
|
|
}
|
|
|
|
void uiShutdown()
|
|
{
|
|
delete g_ui.ib;
|
|
delete g_ui.vb;
|
|
}
|
|
|
|
void uiDumpBuffers()
|
|
{
|
|
Msg( "--- UI Vertex Buffer ---" );
|
|
|
|
g_ui.vertices = (UIVertex*)g_ui.vb->MapBuffer(BufferAccess::WRITE_ONLY);
|
|
assert(g_ui.vertices);
|
|
|
|
for ( int i = 0; i < g_ui.position; i++ )
|
|
{
|
|
Msg( "%i: POSITION = %.2f %.2f", i, g_ui.vertices[ i ].position.x, g_ui.vertices[ i ].position.y );
|
|
Msg( "%i: TEXCOORD = %.2f %.2f", i, g_ui.vertices[ i ].uv.x, g_ui.vertices[ i ].uv.y );
|
|
Msg( "%i: COLOR = %.2f %.2f %.2f %.2f", i,
|
|
g_ui.vertices[ i ].color.x,
|
|
g_ui.vertices[ i ].color.y,
|
|
g_ui.vertices[ i ].color.z,
|
|
g_ui.vertices[ i ].color.w);
|
|
}
|
|
|
|
Msg( "------------------------" );
|
|
|
|
g_ui.vb->UnmapBuffer();
|
|
}
|
|
|
|
void uiBeginRender()
|
|
{
|
|
g_ui.vertices = (UIVertex*)g_ui.vb->MapBuffer(BufferAccess::WRITE_ONLY);
|
|
assert(g_ui.vertices);
|
|
|
|
g_ui.indices = (uint16_t*)g_ui.ib->MapBuffer(BufferAccess::WRITE_ONLY);
|
|
assert(g_ui.indices);
|
|
}
|
|
|
|
void uiDrawQuad(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& d, const Vec4& color)
|
|
{
|
|
DrawInfo& drawInfo = g_ui.drawInfo[g_ui.count];
|
|
drawInfo.vxcount = 4;
|
|
drawInfo.idxcount = 6;
|
|
|
|
g_ui.indices[g_ui.Indexposition + 0] = g_ui.currentIdx;
|
|
g_ui.indices[g_ui.Indexposition + 1] = g_ui.currentIdx + 1;
|
|
g_ui.indices[g_ui.Indexposition + 2] = g_ui.currentIdx + 2;
|
|
g_ui.indices[g_ui.Indexposition + 3] = g_ui.currentIdx;
|
|
g_ui.indices[g_ui.Indexposition + 4] = g_ui.currentIdx + 2;
|
|
g_ui.indices[g_ui.Indexposition + 5] = g_ui.currentIdx + 3;
|
|
g_ui.vertices[g_ui.position + 0].position = a; g_ui.vertices[g_ui.position + 0].color = color;
|
|
g_ui.vertices[g_ui.position + 1].position = b; g_ui.vertices[g_ui.position + 1].color = color;
|
|
g_ui.vertices[g_ui.position + 2].position = c; g_ui.vertices[g_ui.position + 2].color = color;
|
|
g_ui.vertices[g_ui.position + 3].position = d; g_ui.vertices[g_ui.position + 3].color = color;
|
|
|
|
// texcoord
|
|
g_ui.vertices[g_ui.position + 0].uv = Vec2{ 0.0f, 1.0f };
|
|
g_ui.vertices[g_ui.position + 1].uv = Vec2{ 1.0f, 1.0f };
|
|
g_ui.vertices[g_ui.position + 2].uv = Vec2{ 1.0f, 0.0f };
|
|
g_ui.vertices[g_ui.position + 3].uv = Vec2{ 0.0f, 0.0f };
|
|
|
|
g_ui.currentIdx += 4;
|
|
g_ui.Indexposition += 6;
|
|
g_ui.position += 4;
|
|
g_ui.count++;
|
|
}
|
|
|
|
static inline float Rsqrt(float x) { return 1.0f / sqrtf(x); }
|
|
#define NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = Rsqrt(d2); VX *= inv_len; VY *= inv_len; } } (void)0
|
|
|
|
void uiDrawLines(const Vec2* drawPoints, const size_t pointsCount, bool closed, const Vec4& color)
|
|
{
|
|
float thickness = 2.1f;
|
|
|
|
const int count = closed ? pointsCount : pointsCount - 1;
|
|
const int vtxCount = (count) * 4;
|
|
const int idxCount = (count) * 6;
|
|
|
|
for (int i1 = 0; i1 < count; i1++)
|
|
{
|
|
const int i2 = (i1 + 1) == pointsCount ? 0 : i1 + 1;
|
|
const Vec2& p1 = drawPoints[i1];
|
|
const Vec2& p2 = drawPoints[i2];
|
|
|
|
float dx = p2.x - p1.x;
|
|
float dy = p2.y - p1.y;
|
|
NORMALIZE2F_OVER_ZERO(dx, dy);
|
|
dx *= (thickness * 0.5f);
|
|
dy *= (thickness * 0.5f);
|
|
|
|
g_ui.vertices[g_ui.position + 0].position.x = p1.x + dy; g_ui.vertices[g_ui.position + 0].position.y = p1.y - dx; g_ui.vertices[g_ui.position + 0].color = color;
|
|
g_ui.vertices[g_ui.position + 1].position.x = p2.x + dy; g_ui.vertices[g_ui.position + 1].position.y = p2.y - dx; g_ui.vertices[g_ui.position + 1].color = color;
|
|
g_ui.vertices[g_ui.position + 2].position.x = p2.x - dy; g_ui.vertices[g_ui.position + 2].position.y = p2.y + dx; g_ui.vertices[g_ui.position + 2].color = color;
|
|
g_ui.vertices[g_ui.position + 3].position.x = p1.x - dy; g_ui.vertices[g_ui.position + 3].position.y = p1.y + dx; g_ui.vertices[g_ui.position + 3].color = color;
|
|
|
|
g_ui.indices[g_ui.Indexposition + 0] = g_ui.currentIdx;
|
|
g_ui.indices[g_ui.Indexposition + 1] = g_ui.currentIdx + 1;
|
|
g_ui.indices[g_ui.Indexposition + 2] = g_ui.currentIdx + 2;
|
|
g_ui.indices[g_ui.Indexposition + 3] = g_ui.currentIdx;
|
|
g_ui.indices[g_ui.Indexposition + 4] = g_ui.currentIdx + 2;
|
|
g_ui.indices[g_ui.Indexposition + 5] = g_ui.currentIdx + 3;
|
|
g_ui.currentIdx += 4;
|
|
g_ui.Indexposition += 6;
|
|
g_ui.position += 4;
|
|
|
|
DrawInfo& drawInfo = g_ui.drawInfo[g_ui.count];
|
|
drawInfo.vxcount = 4;
|
|
drawInfo.idxcount = 6;
|
|
g_ui.count++;
|
|
}
|
|
}
|
|
|
|
void uiDrawRect(const Vec2& position, const Vec2& size, const Vec4& color)
|
|
{
|
|
Vec2 quad[4];
|
|
quad[0] = { position.x, position.y };
|
|
quad[1] = { position.x + size.x, position.y };
|
|
quad[2] = { position.x + size.x, position.y + size.y };
|
|
quad[3] = { position.x, position.y + size.y };
|
|
uiDrawQuad(quad[0], quad[1], quad[2], quad[3], color);
|
|
}
|
|
|
|
void uiSetTexture(Texture2D* texture)
|
|
{
|
|
g_ui.activetexture = texture ? texture : g_ui.defaultTexture;
|
|
}
|
|
|
|
void uiSetTextureByName(const char* filename)
|
|
{
|
|
uiSetTexture( g_texturesManager->LoadTexture2D( filename ) );
|
|
}
|
|
|
|
void uiEndRender()
|
|
{
|
|
g_ui.indices = nullptr;
|
|
g_ui.vertices = nullptr;
|
|
|
|
g_ui.ib->UnmapBuffer();
|
|
g_ui.vb->UnmapBuffer();
|
|
|
|
int x = 0, y = 0, w = g_renderView.width, h = g_renderView.height;
|
|
g_renderDevice->SetViewport(x, y, w, h);
|
|
|
|
float L = x;
|
|
float R = x + w;
|
|
float T = y;
|
|
float B = y + h;
|
|
#if defined(GL_CLIP_ORIGIN)
|
|
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
|
|
#endif
|
|
const float orthoProjection[4][4] =
|
|
{
|
|
{ 2.0f / (R - L), 0.0f, 0.0f, 0.0f },
|
|
{ 0.0f, 2.0f / (T - B), 0.0f, 0.0f },
|
|
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
|
{ (R + L) / (L - R), (T + B) / (B - T), 0.0f, 1.0f },
|
|
};
|
|
|
|
if ( g_ui.activetexture == nullptr )
|
|
g_ui.activetexture = g_ui.defaultTexture;
|
|
|
|
g_texturesManager->SetTexture( 0, g_ui.activetexture );
|
|
g_ui.activetexture->setMin(TextureFilter::Linear);
|
|
g_ui.activetexture->setMag(TextureFilter::Linear);
|
|
g_ui.activetexture->setWrapS(TextureWrap::ClampToEdge);
|
|
g_ui.activetexture->setWrapT(TextureWrap::ClampToEdge);
|
|
|
|
g_shaderSystem->SetShader( g_ui.shader );
|
|
g_shaderSystem->SetUniformMatrix( g_ui.shader, UNIFORM_PROJ_MATRIX, orthoProjection );
|
|
|
|
g_renderDevice->SetVerticesBuffer( g_ui.vb );
|
|
g_renderDevice->SetIndicesBuffer( g_ui.ib );
|
|
|
|
// Enable blending
|
|
g_renderDevice->SetBlending( true );
|
|
g_renderDevice->SetBlendingFunction( BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA );
|
|
|
|
// Disable depth
|
|
g_renderDevice->SetDepthTest( false );
|
|
g_renderDevice->SetBackfaceCull( false );
|
|
|
|
g_renderDevice->DrawElements( PT_TRIANGLES, g_ui.Indexposition, true );
|
|
|
|
// Uncomment for UI VB debugging
|
|
//uiDumpBuffers();
|
|
|
|
g_ui.currentIdx = 0;
|
|
g_ui.Indexposition = 0;
|
|
g_ui.position = 0;
|
|
g_ui.count = 0;
|
|
}
|
|
|
|
typedef struct Character {
|
|
int codePoint, x, y, width, height, originX, originY;
|
|
} Character;
|
|
|
|
typedef struct Font {
|
|
const char* name;
|
|
int size, bold, italic, width, height, characterCount;
|
|
Character* characters;
|
|
} Font;
|
|
|
|
static Character characters_Courier_New[] = {
|
|
{' ', 36, 61, 3, 3, 1, 1},
|
|
{'!', 498, 0, 10, 20, -1, 16},
|
|
{'"', 423, 43, 14, 13, 1, 16},
|
|
{'#', 160, 0, 16, 22, 2, 17},
|
|
{'$', 47, 0, 16, 23, 2, 17},
|
|
{'%', 357, 0, 16, 20, 2, 16},
|
|
{'&', 202, 24, 15, 19, 1, 15},
|
|
{'\'', 448, 43, 10, 13, -1, 16},
|
|
{'(', 111, 0, 11, 23, -2, 16},
|
|
{')', 122, 0, 11, 23, 1, 16},
|
|
{'*', 357, 43, 16, 15, 2, 16},
|
|
{'+', 392, 24, 18, 18, 3, 15},
|
|
{',', 437, 43, 11, 13, -1, 6},
|
|
{'-', 20, 61, 16, 9, 2, 10},
|
|
{'.', 474, 43, 10, 10, -1, 6},
|
|
{'/', 0, 0, 16, 24, 2, 18},
|
|
{'0', 373, 0, 16, 20, 2, 16},
|
|
{'1', 106, 24, 16, 19, 2, 16},
|
|
{'2', 122, 24, 16, 19, 2, 16},
|
|
{'3', 389, 0, 16, 20, 2, 16},
|
|
{'4', 138, 24, 16, 19, 2, 16},
|
|
{'5', 405, 0, 16, 20, 2, 16},
|
|
{'6', 453, 0, 15, 20, 1, 16},
|
|
{'7', 154, 24, 16, 19, 2, 16},
|
|
{'8', 421, 0, 16, 20, 2, 16},
|
|
{'9', 468, 0, 15, 20, 1, 16},
|
|
{':', 292, 43, 10, 16, -1, 12},
|
|
{';', 120, 43, 12, 18, 0, 12},
|
|
{'<', 297, 24, 19, 18, 4, 15},
|
|
{'=', 405, 43, 18, 13, 3, 12},
|
|
{'>', 316, 24, 19, 18, 3, 15},
|
|
{'?', 483, 0, 15, 20, 1, 16},
|
|
{'@', 232, 0, 15, 21, 2, 16},
|
|
{'A', 217, 24, 20, 18, 4, 15},
|
|
{'B', 410, 24, 18, 18, 3, 15},
|
|
{'C', 285, 0, 18, 20, 3, 16},
|
|
{'D', 428, 24, 18, 18, 3, 15},
|
|
{'E', 446, 24, 18, 18, 3, 15},
|
|
{'F', 54, 43, 17, 18, 2, 15},
|
|
{'G', 303, 0, 18, 20, 3, 16},
|
|
{'H', 464, 24, 18, 18, 3, 15},
|
|
{'I', 88, 43, 16, 18, 2, 15},
|
|
{'J', 0, 24, 18, 19, 2, 15},
|
|
{'K', 335, 24, 19, 18, 3, 15},
|
|
{'L', 482, 24, 18, 18, 3, 15},
|
|
{'M', 237, 24, 20, 18, 4, 15},
|
|
{'N', 354, 24, 19, 18, 4, 15},
|
|
{'O', 321, 0, 18, 20, 3, 16},
|
|
{'P', 71, 43, 17, 18, 2, 15},
|
|
{'Q', 142, 0, 18, 22, 3, 16},
|
|
{'R', 373, 24, 19, 18, 3, 15},
|
|
{'S', 437, 0, 16, 20, 2, 16},
|
|
{'T', 0, 43, 18, 18, 3, 15},
|
|
{'U', 18, 24, 18, 19, 3, 15},
|
|
{'V', 257, 24, 20, 18, 4, 15},
|
|
{'W', 277, 24, 20, 18, 4, 15},
|
|
{'X', 18, 43, 18, 18, 3, 15},
|
|
{'Y', 36, 43, 18, 18, 3, 15},
|
|
{'Z', 104, 43, 16, 18, 2, 15},
|
|
{'[', 63, 0, 12, 23, -1, 16},
|
|
{'\\', 16, 0, 16, 24, 2, 18},
|
|
{']', 75, 0, 12, 23, 1, 16},
|
|
{'^', 389, 43, 16, 14, 2, 17},
|
|
{'_', 0, 61, 20, 9, 4, -1},
|
|
{'`', 484, 43, 10, 10, -1, 17},
|
|
{'a', 132, 43, 18, 17, 3, 13},
|
|
{'b', 247, 0, 19, 20, 4, 16},
|
|
{'c', 186, 43, 17, 17, 2, 13},
|
|
{'d', 266, 0, 19, 20, 3, 16},
|
|
{'e', 150, 43, 18, 17, 3, 13},
|
|
{'f', 72, 24, 17, 19, 2, 16},
|
|
{'g', 214, 0, 18, 21, 3, 13},
|
|
{'h', 36, 24, 18, 19, 3, 16},
|
|
{'i', 170, 24, 16, 19, 2, 16},
|
|
{'j', 32, 0, 15, 24, 2, 16},
|
|
{'k', 54, 24, 18, 19, 3, 16},
|
|
{'l', 186, 24, 16, 19, 2, 16},
|
|
{'m', 219, 43, 20, 16, 4, 13},
|
|
{'n', 239, 43, 18, 16, 3, 13},
|
|
{'o', 168, 43, 18, 17, 3, 13},
|
|
{'p', 176, 0, 19, 21, 4, 13},
|
|
{'q', 195, 0, 19, 21, 3, 13},
|
|
{'r', 275, 43, 17, 16, 2, 13},
|
|
{'s', 203, 43, 16, 17, 2, 13},
|
|
{'t', 89, 24, 17, 19, 2, 15},
|
|
{'u', 257, 43, 18, 16, 3, 12},
|
|
{'v', 302, 43, 19, 15, 3, 12},
|
|
{'w', 321, 43, 18, 15, 3, 12},
|
|
{'x', 339, 43, 18, 15, 3, 12},
|
|
{'y', 339, 0, 18, 20, 3, 12},
|
|
{'z', 373, 43, 16, 15, 2, 12},
|
|
{'{', 87, 0, 12, 23, 0, 16},
|
|
{'|', 133, 0, 9, 23, -2, 16},
|
|
{'}', 99, 0, 12, 23, 0, 16},
|
|
{'~', 458, 43, 16, 11, 2, 11},
|
|
};
|
|
|
|
static Font font_Courier_New = { "Courier New", 20, 1, 0, 512, 128, 95, characters_Courier_New };
|
|
|
|
static Character characters_Arial[] = {
|
|
{' ', 10, 61, 3, 3, 1, 1},
|
|
{'!', 205, 34, 5, 15, 0, 14},
|
|
{'"', 202, 49, 8, 7, 1, 14},
|
|
{'#', 187, 19, 12, 15, 1, 14},
|
|
{'$', 71, 0, 12, 18, 1, 15},
|
|
{'%', 162, 0, 16, 15, 0, 14},
|
|
{'&', 208, 0, 14, 15, 1, 14},
|
|
{'\'', 210, 49, 5, 7, 1, 14},
|
|
{'(', 35, 0, 7, 19, 0, 14},
|
|
{')', 42, 0, 7, 19, 0, 14},
|
|
{'*', 193, 49, 9, 7, 1, 14},
|
|
{'+', 161, 49, 11, 10, 0, 11},
|
|
{',', 215, 49, 5, 7, 0, 3},
|
|
{'-', 246, 49, 8, 4, 1, 6},
|
|
{'.', 0, 61, 5, 4, 0, 3},
|
|
{'/', 177, 34, 7, 15, 1, 14},
|
|
{'0', 199, 19, 12, 15, 1, 14},
|
|
{'1', 184, 34, 7, 15, -1, 14},
|
|
{'2', 84, 34, 11, 15, 1, 14},
|
|
{'3', 211, 19, 12, 15, 1, 14},
|
|
{'4', 223, 19, 12, 15, 1, 14},
|
|
{'5', 235, 19, 12, 15, 1, 14},
|
|
{'6', 0, 34, 12, 15, 1, 14},
|
|
{'7', 12, 34, 12, 15, 1, 14},
|
|
{'8', 24, 34, 12, 15, 1, 14},
|
|
{'9', 36, 34, 12, 15, 1, 14},
|
|
{':', 156, 49, 5, 11, 0, 10},
|
|
{';', 223, 34, 5, 14, 0, 10},
|
|
{'<', 134, 49, 11, 11, 0, 12},
|
|
{'=', 182, 49, 11, 8, 0, 10},
|
|
{'>', 145, 49, 11, 11, 0, 12},
|
|
{'?', 95, 34, 11, 15, 1, 14},
|
|
{'@', 0, 0, 19, 19, 0, 14},
|
|
{'A', 222, 0, 14, 15, 1, 14},
|
|
{'B', 48, 34, 12, 15, 0, 14},
|
|
{'C', 236, 0, 14, 15, 0, 14},
|
|
{'D', 70, 19, 13, 15, 0, 14},
|
|
{'E', 60, 34, 12, 15, 0, 14},
|
|
{'F', 72, 34, 12, 15, 0, 14},
|
|
{'G', 0, 19, 14, 15, 0, 14},
|
|
{'H', 83, 19, 13, 15, 0, 14},
|
|
{'I', 210, 34, 5, 15, 0, 14},
|
|
{'J', 139, 34, 10, 15, 1, 14},
|
|
{'K', 96, 19, 13, 15, 0, 14},
|
|
{'L', 106, 34, 11, 15, 0, 14},
|
|
{'M', 178, 0, 15, 15, 0, 14},
|
|
{'N', 109, 19, 13, 15, 0, 14},
|
|
{'O', 193, 0, 15, 15, 0, 14},
|
|
{'P', 122, 19, 13, 15, 0, 14},
|
|
{'Q', 83, 0, 16, 16, 1, 14},
|
|
{'R', 14, 19, 14, 15, 0, 14},
|
|
{'S', 135, 19, 13, 15, 1, 14},
|
|
{'T', 148, 19, 13, 15, 1, 14},
|
|
{'U', 161, 19, 13, 15, 0, 14},
|
|
{'V', 28, 19, 14, 15, 1, 14},
|
|
{'W', 143, 0, 19, 15, 1, 14},
|
|
{'X', 42, 19, 14, 15, 1, 14},
|
|
{'Y', 56, 19, 14, 15, 1, 14},
|
|
{'Z', 174, 19, 13, 15, 1, 14},
|
|
{'[', 49, 0, 6, 19, 0, 14},
|
|
{'\\', 191, 34, 7, 15, 1, 14},
|
|
{']', 55, 0, 6, 19, 1, 14},
|
|
{'^', 172, 49, 10, 9, 1, 14},
|
|
{'_', 232, 49, 14, 4, 2, -1},
|
|
{'`', 5, 61, 5, 4, 0, 14},
|
|
{'a', 15, 49, 12, 12, 1, 11},
|
|
{'b', 117, 34, 11, 15, 0, 14},
|
|
{'c', 51, 49, 11, 12, 1, 11},
|
|
{'d', 128, 34, 11, 15, 1, 14},
|
|
{'e', 27, 49, 12, 12, 1, 11},
|
|
{'f', 169, 34, 8, 15, 1, 14},
|
|
{'g', 99, 0, 11, 16, 1, 11},
|
|
{'h', 149, 34, 10, 15, 0, 14},
|
|
{'i', 215, 34, 4, 15, 0, 14},
|
|
{'j', 61, 0, 6, 19, 2, 14},
|
|
{'k', 159, 34, 10, 15, 0, 14},
|
|
{'l', 219, 34, 4, 15, 0, 14},
|
|
{'m', 228, 34, 15, 12, 0, 11},
|
|
{'n', 106, 49, 10, 12, 0, 11},
|
|
{'o', 39, 49, 12, 12, 1, 11},
|
|
{'p', 110, 0, 11, 16, 0, 11},
|
|
{'q', 121, 0, 11, 16, 1, 11},
|
|
{'r', 126, 49, 8, 12, 0, 11},
|
|
{'s', 62, 49, 11, 12, 1, 11},
|
|
{'t', 198, 34, 7, 15, 1, 14},
|
|
{'u', 116, 49, 10, 12, 0, 11},
|
|
{'v', 73, 49, 11, 12, 1, 11},
|
|
{'w', 0, 49, 15, 12, 1, 11},
|
|
{'x', 84, 49, 11, 12, 1, 11},
|
|
{'y', 132, 0, 11, 16, 1, 11},
|
|
{'z', 95, 49, 11, 12, 1, 11},
|
|
{'{', 19, 0, 8, 19, 1, 14},
|
|
{'|', 67, 0, 4, 19, 0, 14},
|
|
{'}', 27, 0, 8, 19, 1, 14},
|
|
{'~', 220, 49, 12, 5, 1, 9},
|
|
};
|
|
|
|
static Font font_Arial = { "Arial", 18, 0, 0, 256, 128, 95, characters_Arial };
|