refactor font code into classes
This commit is contained in:
@@ -107,35 +107,12 @@ void App::init()
|
|||||||
printf("error loading image\n");
|
printf("error loading image\n");
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
FILE* font_file = fopen("C:\\Windows\\Fonts\\arial.ttf", "rb");
|
const char* ttf = "C:\\Windows\\Fonts\\arial.ttf";
|
||||||
#else
|
#else
|
||||||
FILE* font_file = fopen("/Library/Fonts/Arial.ttf", "rb");
|
const char* ttf = "/Library/Fonts/Arial.ttf";
|
||||||
#endif
|
#endif
|
||||||
if (font_file)
|
FontManager::load(kFont::Arial_11, ttf);
|
||||||
{
|
text.create();
|
||||||
fseek(font_file, 0, SEEK_END);
|
|
||||||
long sz = ftell(font_file);
|
|
||||||
auto data = std::make_unique<uint8_t[]>(sz);
|
|
||||||
fseek(font_file, 0, SEEK_SET);
|
|
||||||
auto bytes = fread(data.get(), 1, sz, font_file);
|
|
||||||
assert(bytes==sz);
|
|
||||||
auto bitmap = std::make_unique<uint8_t[]>(w*h);
|
|
||||||
chars.resize(num_chars);
|
|
||||||
int ret = stbtt_BakeFontBitmap(data.get(), 0, 50, bitmap.get(), w, h, start_char, num_chars, chars.data());
|
|
||||||
font_tex.create(w, h, GL_RED, bitmap.get());
|
|
||||||
|
|
||||||
glGenBuffers(2, font_buffers);
|
|
||||||
glGenVertexArrays(1, &font_array);
|
|
||||||
|
|
||||||
glBindVertexArray(font_array);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
|
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float)*2));
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
plane.create<1>(400, 400);
|
plane.create<1>(400, 400);
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
@@ -172,7 +149,6 @@ void App::update(float dt)
|
|||||||
layout[main_id].update(width, height);
|
layout[main_id].update(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
for (auto& n : layout[main_id])
|
for (auto& n : layout[main_id])
|
||||||
@@ -185,48 +161,10 @@ void App::update(float dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
*/
|
|
||||||
glm::mat4 proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
|
glm::mat4 proj = glm::ortho(0.f, width, height, 0.f, -1.f, 1.f);
|
||||||
glm::mat4 tran = glm::translate(glm::vec3(200, 200, 0));
|
glm::mat4 tran = glm::translate(glm::vec3(200, 200, 0));
|
||||||
|
|
||||||
|
|
||||||
if (chars.size())
|
|
||||||
{
|
|
||||||
static char str[64];
|
|
||||||
static int counter = 0;
|
|
||||||
counter++;
|
|
||||||
sprintf(str, "frame %04d", counter);
|
|
||||||
const auto len = strlen(str);
|
|
||||||
float x = 0;
|
|
||||||
float y = 0;
|
|
||||||
std::vector<glm::vec4> v;
|
|
||||||
std::vector<GLushort> idx;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
int c = str[i] - start_char;
|
|
||||||
stbtt_aligned_quad q;
|
|
||||||
stbtt_GetBakedQuad(chars.data(), w, h, c, &x, &y, &q, true);
|
|
||||||
auto n = v.size();
|
|
||||||
v.emplace_back(q.x0, q.y1, q.s0, q.t1);
|
|
||||||
v.emplace_back(q.x0, q.y0, q.s0, q.t0);
|
|
||||||
v.emplace_back(q.x1, q.y0, q.s1, q.t0);
|
|
||||||
v.emplace_back(q.x1, q.y1, q.s1, q.t1);
|
|
||||||
idx.push_back(n+0);
|
|
||||||
idx.push_back(n+1);
|
|
||||||
idx.push_back(n+2);
|
|
||||||
idx.push_back(n+0);
|
|
||||||
idx.push_back(n+2);
|
|
||||||
idx.push_back(n+3);
|
|
||||||
}
|
|
||||||
font_array_count = (int)idx.size();
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx.size() * sizeof(GLushort), idx.data(), GL_STATIC_DRAW);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, v.size() * sizeof(glm::vec4), v.data(), GL_STATIC_DRAW);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
font_tex.bind();
|
font_tex.bind();
|
||||||
sampler.bind(0);
|
sampler.bind(0);
|
||||||
|
|||||||
13
engine/app.h
13
engine/app.h
@@ -4,23 +4,16 @@
|
|||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
class App
|
class App
|
||||||
{
|
{
|
||||||
Sampler sampler;
|
Sampler sampler;
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
LayoutManager layout;
|
LayoutManager layout;
|
||||||
stbtt_fontinfo font;
|
|
||||||
Texture2D font_tex;
|
|
||||||
std::vector<stbtt_bakedchar> chars;
|
|
||||||
Plane plane;
|
Plane plane;
|
||||||
GLuint font_array;
|
Font font;
|
||||||
int font_array_count = 0;
|
TextMesh text;
|
||||||
GLuint font_buffers[2];
|
|
||||||
const int w = 512;
|
|
||||||
const int h = 512;
|
|
||||||
const int num_chars = 96;
|
|
||||||
const int start_char = 32;
|
|
||||||
public:
|
public:
|
||||||
static App I;
|
static App I;
|
||||||
float width;
|
float width;
|
||||||
|
|||||||
@@ -1,5 +1,92 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
|
||||||
|
std::map<kFont, Font> FontManager::m_fonts;
|
||||||
|
|
||||||
|
bool Font::load(const char* ttf)
|
||||||
|
{
|
||||||
|
FILE* font_file = fopen(ttf, "rb");
|
||||||
|
if (font_file)
|
||||||
|
{
|
||||||
|
fseek(font_file, 0, SEEK_END);
|
||||||
|
long sz = ftell(font_file);
|
||||||
|
auto data = std::make_unique<uint8_t[]>(sz);
|
||||||
|
fseek(font_file, 0, SEEK_SET);
|
||||||
|
auto bytes = fread(data.get(), 1, sz, font_file);
|
||||||
|
assert(bytes==sz);
|
||||||
|
auto bitmap = std::make_unique<uint8_t[]>(w*h);
|
||||||
|
chars.resize(num_chars);
|
||||||
|
int ret = stbtt_BakeFontBitmap(data.get(), 0, 50, bitmap.get(), w, h, start_char, num_chars, chars.data());
|
||||||
|
font_tex.create(w, h, GL_RED, bitmap.get());
|
||||||
|
fclose(font_file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontManager::load(kFont id, const char *ttf)
|
||||||
|
{
|
||||||
|
return m_fonts[id].load(ttf);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Font& FontManager::get(kFont id)
|
||||||
|
{
|
||||||
|
return m_fonts[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextMesh::create()
|
||||||
|
{
|
||||||
|
glGenBuffers(2, font_buffers);
|
||||||
|
glGenVertexArrays(1, &font_array);
|
||||||
|
|
||||||
|
glBindVertexArray(font_array);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float)*2));
|
||||||
|
glBindVertexArray(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextMesh::update(kFont id, const char* text)
|
||||||
|
{
|
||||||
|
auto& f = FontManager::get(id);
|
||||||
|
if (f.chars.size())
|
||||||
|
{
|
||||||
|
static char str[64];
|
||||||
|
static int counter = 0;
|
||||||
|
counter++;
|
||||||
|
sprintf(str, "frame %04d", counter);
|
||||||
|
const auto len = strlen(str);
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
std::vector<glm::vec4> v;
|
||||||
|
std::vector<GLushort> idx;
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
int c = str[i] - f.start_char;
|
||||||
|
stbtt_aligned_quad q;
|
||||||
|
stbtt_GetBakedQuad((stbtt_bakedchar*)f.chars.data(), f.w, f.h, c, &x, &y, &q, true);
|
||||||
|
auto n = v.size();
|
||||||
|
v.emplace_back(q.x0, q.y1, q.s0, q.t1);
|
||||||
|
v.emplace_back(q.x0, q.y0, q.s0, q.t0);
|
||||||
|
v.emplace_back(q.x1, q.y0, q.s1, q.t0);
|
||||||
|
v.emplace_back(q.x1, q.y1, q.s1, q.t1);
|
||||||
|
idx.push_back(n+0);
|
||||||
|
idx.push_back(n+1);
|
||||||
|
idx.push_back(n+2);
|
||||||
|
idx.push_back(n+0);
|
||||||
|
idx.push_back(n+2);
|
||||||
|
idx.push_back(n+3);
|
||||||
|
}
|
||||||
|
font_array_count = (int)idx.size();
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx.size() * sizeof(GLushort), idx.data(), GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, v.size() * sizeof(glm::vec4), v.data(), GL_STATIC_DRAW);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,40 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "texture.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
enum class kFont : uint16_t
|
||||||
|
{
|
||||||
|
Arial_11 = const_hash("arial-16"),
|
||||||
|
};
|
||||||
|
|
||||||
|
class Font
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const int w = 512;
|
||||||
|
const int h = 512;
|
||||||
|
const int num_chars = 96;
|
||||||
|
const int start_char = 32;
|
||||||
|
stbtt_fontinfo font;
|
||||||
|
Texture2D font_tex;
|
||||||
|
std::vector<stbtt_bakedchar> chars;
|
||||||
|
|
||||||
|
bool load(const char* ttf);
|
||||||
|
};
|
||||||
|
|
||||||
|
class FontManager
|
||||||
|
{
|
||||||
|
static std::map<kFont, Font> m_fonts;
|
||||||
|
public:
|
||||||
|
static bool load(kFont id, const char* ttf);
|
||||||
|
static const Font& get(kFont id);
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLuint font_array = 0;
|
||||||
|
int font_array_count = 0;
|
||||||
|
GLuint font_buffers[2] = {0, 0};
|
||||||
|
bool create();
|
||||||
|
void update(kFont id, const char* text);
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ protected:
|
|||||||
GLvoid* ioff[2]{ 0 };
|
GLvoid* ioff[2]{ 0 };
|
||||||
struct vertex_t { glm::vec4 pos; glm::vec2 uvs; };
|
struct vertex_t { glm::vec4 pos; glm::vec2 uvs; };
|
||||||
public:
|
public:
|
||||||
// att::AttrubutesMap attribs;
|
|
||||||
bool create_buffers(GLvoid* idx, GLvoid* vertices, int isize, int vsize);
|
bool create_buffers(GLvoid* idx, GLvoid* vertices, int isize, int vsize);
|
||||||
void draw_fill() const;
|
void draw_fill() const;
|
||||||
void draw_stroke() const;
|
void draw_stroke() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user