Add some methods to Font for usage in GUI

This commit is contained in:
mrkubax10 2023-06-20 11:06:50 +02:00
parent aa3c35ed1a
commit 6500ffd1d9
2 changed files with 35 additions and 14 deletions

View File

@ -26,7 +26,6 @@ SOFTWARE.
#include "common/logger.hpp" #include "common/logger.hpp"
#include <vector>
#include <locale> #include <locale>
#include <codecvt> #include <codecvt>
@ -58,42 +57,58 @@ bool Font::load_from_file(const std::string& path) {
return true; return true;
} }
std::unique_ptr<Surface> Font::render_text(const std::string& text, unsigned size, const glm::vec4ub& color) { void Font::render_glyphs(const std::string& text, unsigned size, const glm::vec4ub& color, std::vector<std::unique_ptr<RasterizedGlyph>>& output) {
std::unique_ptr<Surface> result;
if(size!=m_prev_size) { if(size!=m_prev_size) {
if(FT_Set_Char_Size(m_face, 0, size*64, 0, 0)) { if(FT_Set_Char_Size(m_face, 0, size*64, 0, 0)) {
LOG_ERROR("Failed to set size %d for Font %p", size, this); LOG_ERROR("Failed to set size %d for Font %p", size, this);
return result; return;
} }
m_prev_size = size; m_prev_size = size;
} }
std::vector<std::unique_ptr<RasterizedGlyph>> character_surfaces;
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter; std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
std::u32string converted = converter.from_bytes(text); std::u32string converted = converter.from_bytes(text);
unsigned x_pos = 0;
for(char32_t ch : converted) {
output.push_back(std::move(render_glyph(ch, size, color)));
RasterizedGlyph* glyph = output.back().get();
glyph->m_x = x_pos;
glyph->m_y = 0; // TODO: Update this when multiline text rendering will be supported
x_pos+=glyph->m_advance_x;
}
}
std::unique_ptr<Surface> Font::render_text(const std::vector<std::unique_ptr<RasterizedGlyph>>& glyphs) {
std::unique_ptr<Surface> result;
unsigned final_surface_width = 0; unsigned final_surface_width = 0;
int final_surface_height = 0; int final_surface_height = 0;
int surface_text_line = 0; int surface_text_line = 0;
for(char32_t ch : converted) { for(const std::unique_ptr<RasterizedGlyph>& glyph : glyphs) {
character_surfaces.push_back(std::move(render_glyph(ch, size, color))); final_surface_width+=glyph->m_advance_x;
final_surface_width+=character_surfaces.back()->m_advance_x; if(static_cast<unsigned>(surface_text_line)<glyph->m_surface->get_height())
if(static_cast<unsigned>(surface_text_line)<character_surfaces.back()->m_surface->get_height()) surface_text_line = glyph->m_surface->get_height();
surface_text_line = character_surfaces.back()->m_surface->get_height(); const int current_surface_height = surface_text_line-glyph->m_top+glyph->m_surface->get_height();
const int current_surface_height = surface_text_line-character_surfaces.back()->m_top+character_surfaces.back()->m_surface->get_height();
if(current_surface_height>final_surface_height) if(current_surface_height>final_surface_height)
final_surface_height = current_surface_height; final_surface_height = current_surface_height;
} }
result = std::make_unique<Surface>(final_surface_width, final_surface_height, glm::vec4ub(0, 0, 0, 0)); result = std::make_unique<Surface>(final_surface_width, final_surface_height, glm::vec4ub(0, 0, 0, 0));
unsigned x_pos = 0; unsigned x_pos = 0;
for(const std::unique_ptr<RasterizedGlyph>& glyph : character_surfaces) { for(const std::unique_ptr<RasterizedGlyph>& glyph : glyphs) {
result->blit_surface(static_cast<int>(x_pos), surface_text_line-glyph->m_top, *glyph->m_surface); result->blit_surface(glyph->m_x, surface_text_line-glyph->m_top, *glyph->m_surface);
x_pos+=glyph->m_advance_x; x_pos+=glyph->m_advance_x;
} }
return result; return result;
} }
std::unique_ptr<Surface> Font::render_text(const std::string& text, unsigned size, const glm::vec4ub& color) {
std::vector<std::unique_ptr<RasterizedGlyph>> character_surfaces;
render_glyphs(text, size, color, character_surfaces);
return render_text(character_surfaces);
}
std::unique_ptr<Font::RasterizedGlyph> Font::render_glyph(unsigned charcode, unsigned size, const glm::vec4ub& color) { std::unique_ptr<Font::RasterizedGlyph> Font::render_glyph(unsigned charcode, unsigned size, const glm::vec4ub& color) {
std::unique_ptr<RasterizedGlyph> result = std::make_unique<Font::RasterizedGlyph>(); std::unique_ptr<RasterizedGlyph> result = std::make_unique<Font::RasterizedGlyph>();

View File

@ -27,6 +27,7 @@ SOFTWARE.
#include <string> #include <string>
#include <memory> #include <memory>
#include <vector>
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
@ -36,17 +37,22 @@ SOFTWARE.
namespace polygun::renderer { namespace polygun::renderer {
class Surface; class Surface;
class Font final { class Font final {
private: public:
struct RasterizedGlyph { struct RasterizedGlyph {
std::unique_ptr<Surface> m_surface; std::unique_ptr<Surface> m_surface;
unsigned m_x;
unsigned m_y;
unsigned m_advance_x; unsigned m_advance_x;
unsigned m_top; unsigned m_top;
}; };
public: public:
Font(); Font();
~Font(); ~Font();
bool load_from_file(const std::string& path); bool load_from_file(const std::string& path);
void render_glyphs(const std::string& text, unsigned size, const glm::vec4ub& color, std::vector<std::unique_ptr<RasterizedGlyph>>& output);
std::unique_ptr<Surface> render_text(const std::vector<std::unique_ptr<RasterizedGlyph>>& glyphs);
std::unique_ptr<Surface> render_text(const std::string& text, unsigned size, const glm::vec4ub& color); std::unique_ptr<Surface> render_text(const std::string& text, unsigned size, const glm::vec4ub& color);
private: private: