main
Brett 2024-11-11 16:47:25 -05:00
parent 9fc44188cc
commit de454940bc
7 changed files with 145 additions and 39 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
include(FetchContent) include(FetchContent)
set(BLT_GRAPHICS_VERSION 1.0.3) set(BLT_GRAPHICS_VERSION 1.0.4)
set(BLT_GRAPHICS_TEST_VERSION 0.0.1) set(BLT_GRAPHICS_TEST_VERSION 0.0.1)
project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION}) project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION})

View File

@ -16,8 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "blt/std/types.h"
#ifndef BLT_WITH_GRAPHICS_FONT_H #ifndef BLT_WITH_GRAPHICS_FONT_H
#define BLT_WITH_GRAPHICS_FONT_H #define BLT_WITH_GRAPHICS_FONT_H
@ -27,6 +25,8 @@
#include <string_view> #include <string_view>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include "blt/std/types.h"
#include <blt/math/vectors.h>
namespace blt::gfx::font namespace blt::gfx::font
{ {
@ -49,7 +49,7 @@ namespace blt::gfx::font
font_face_t& set_pixel_sizes(blt::u32 width, blt::u32 height); font_face_t& set_pixel_sizes(blt::u32 width, blt::u32 height);
std::optional<int> load_char(char c); [[nodiscard]] std::optional<int> load_char(FT_ULong c) const;
[[nodiscard]] FT_Face* get() const [[nodiscard]] FT_Face* get() const
{ {
@ -64,9 +64,20 @@ namespace blt::gfx::font
struct font_file_t struct font_file_t
{ {
std::string_view path; font_face_t font;
blt::u32 character_min_index; blt::u64 character_min_index;
blt::u32 character_max_index; blt::u64 character_max_index;
font_file_t(font_face_t font, u64 characterMinIndex, u64 characterMaxIndex);
};
struct glyph_t
{
blt::vec2ui size;
blt::vec2ui bearing;
blt::i64 advance;
glyph_t(const vec2ui& size, const vec2ui& bearing, blt::i64 advance);
}; };
} }

View File

@ -20,16 +20,46 @@
#define BLT_WITH_GRAPHICS_FONT_RENDERER_H #define BLT_WITH_GRAPHICS_FONT_RENDERER_H
#include <blt/gfx/font/font.h> #include <blt/gfx/font/font.h>
#include <blt/gfx/texture.h>
#include <blt/std/hashmap.h>
#include <blt/std/binary_tree.h>
namespace blt::gfx namespace blt::gfx
{ {
class font_texture_atlas : public texture_gl2D
{
public:
struct bounded_t
{
font::glyph_t glyph;
blt::vec2ui min;
blt::vec2ui max;
};
explicit font_texture_atlas(blt::i32 dimensions);
blt::u64 add_font(const font::font_file_t& file);
blt::u64 add_font(const font::font_file_t& file, blt::u64 start);
bounded_t& get_glyph(blt::u64 c)
{ return glyphs.at(c); }
[[nodiscard]] const bounded_t& get_glyph(blt::u64 c) const
{ return glyphs.at(c); }
private:
blt::hashmap_t<blt::u64, bounded_t> glyphs;
blt::u32 used_width = 0;
blt::u32 used_height = 0;
};
class font_renderer_t class font_renderer_t
{ {
public: public:
explicit font_renderer_t(); explicit font_renderer_t(const std::vector<font::font_file_t>& files, blt::i32 dimensions = 4096);
private: private:
}; };

@ -1 +1 @@
Subproject commit 7bf24a11a53d345b58a7437a1b9768f2da78eeb2 Subproject commit 05e5fcf7f1091d6c85711ff7ce53d840c17e547b

View File

@ -18,6 +18,7 @@
#include <blt/gfx/font/font.h> #include <blt/gfx/font/font.h>
#include <blt/std/logging.h> #include <blt/std/logging.h>
#include <cstring> #include <cstring>
#include <utility>
#include "blt/std/assert.h" #include "blt/std/assert.h"
namespace blt::gfx::font namespace blt::gfx::font
@ -252,13 +253,19 @@ namespace blt::gfx::font
return *this; return *this;
} }
std::optional<int> font_face_t::load_char(char c) std::optional<int> font_face_t::load_char(FT_ULong c) const
{ {
if (int err = FT_Load_Char(*face, c, FT_LOAD_RENDER)) if (int err = FT_Load_Char(*face, c, FT_LOAD_RENDER))
return {err}; return {err};
return {}; return {};
} }
font_file_t::font_file_t(font_face_t font, u64 characterMinIndex, u64 characterMaxIndex):
font(std::move(font)), character_min_index(characterMinIndex), character_max_index(characterMaxIndex)
{}
glyph_t::glyph_t(const vec2ui& size, const vec2ui& bearing, blt::i64 advance): size(size), bearing(bearing), advance(advance)
{}
const unsigned int default_font_compressed_size = 91605; const unsigned int default_font_compressed_size = 91605;
const unsigned int default_font_compressed_data[91608 / 4] = const unsigned int default_font_compressed_data[91608 / 4] =

View File

@ -18,6 +18,63 @@
#include <blt/gfx/renderer/font_renderer.h> #include <blt/gfx/renderer/font_renderer.h>
namespace blt::gfx namespace blt::gfx
{
font_texture_atlas::font_texture_atlas(blt::i32 dimensions): texture_gl2D(dimensions, dimensions, GL_RED)
{}
blt::u64 font_texture_atlas::add_font(const font::font_file_t& file)
{
return add_font(file, file.character_min_index);
}
blt::u64 font_texture_atlas::add_font(const font::font_file_t& file, blt::u64 start)
{
blt::u32 max_height = 0;
for (auto i = start; i < file.character_max_index; i++)
{
// returns an empty optional if there is no error code
if (file.font.load_char(i))
continue;
auto face = *file.font.get();
auto width = face->glyph->bitmap.width;
auto height = face->glyph->bitmap.rows;
max_height = std::max(max_height, height);
// if adding this width overflows, we need to move to the next row.
if (used_width + width > static_cast<blt::u32>(getWidth()))
{
used_height += max_height;
max_height = 0;
used_width = 0;
}
// if we can't fit the height of this character we should move to the next texture atlas.
if (used_height + height > static_cast<blt::u32>(getHeight()))
return i;
auto begin_width = used_width;
auto begin_height = used_height;
auto end_width = used_width + width;
auto end_height = used_height + height;
// upload the texture
upload(face->glyph->bitmap.buffer, GL_RED, 0, static_cast<blt::i32>(begin_width), static_cast<blt::i32>(begin_height),
static_cast<blt::i32>(width), static_cast<blt::i32>(height));
glyphs.insert(std::pair{i, bounded_t{
font::glyph_t{
{width, height},
{face->glyph->bitmap_left, face->glyph->bitmap_top},
face->glyph->advance.x},
{begin_width, begin_height}, {end_width, end_height}}
});
}
return -1;
}
font_renderer_t::font_renderer_t(const std::vector<font::font_file_t>& files, blt::i32 dimensions)
{ {
} }
}

View File

@ -180,33 +180,6 @@ void blt::gfx::texture_gl::setDefaults(GLint type, GLint wrap_type) const
#endif #endif
} }
void blt::gfx::texture_gl2D::upload(void* data, GLint dataColorMode, int level, int x_offset, int y_offset, int sub_width, int sub_height,
GLint dataMode) const
{
if (sub_width < 0)
sub_width = m_width;
if (sub_height < 0)
sub_height = m_height;
bind();
glTexSubImage2D(textureBindType, level, x_offset, y_offset, sub_width, sub_height, dataColorMode, dataMode, data);
generateMipmaps();
unbind();
}
void blt::gfx::texture_gl2D::upload(const blt::gfx::texture_data& file_data) const
{
upload((void*) file_data.data(), file_data.channels() == 4 ? GL_RGBA : GL_RGB, 0, 0, 0, file_data.width(), file_data.height());
}
void blt::gfx::texture_gl2D::upload(void* data, int width, int height, GLint dataColorMode, GLint dataMode)
{
bind();
glTexImage2D(textureBindType, 0, textureColorMode, width, height, 0, dataColorMode, dataMode, data);
generateMipmaps();
unbind();
}
void blt::gfx::texture_gl2D::resize(int width, int height) void blt::gfx::texture_gl2D::resize(int width, int height)
{ {
m_width = width; m_width = width;
@ -238,6 +211,34 @@ blt::gfx::texture_gl2D::texture_gl2D(const blt::gfx::texture_data& data):
unbind(); unbind();
} }
void blt::gfx::texture_gl2D::upload(void* data, GLint dataColorMode, int level, int x_offset, int y_offset, int sub_width, int sub_height,
GLint dataMode) const
{
if (sub_width < 0)
sub_width = m_width;
if (sub_height < 0)
sub_height = m_height;
bind();
glTexSubImage2D(textureBindType, level, x_offset, y_offset, sub_width, sub_height, dataColorMode, dataMode, data);
generateMipmaps();
unbind();
}
void blt::gfx::texture_gl2D::upload(const blt::gfx::texture_data& file_data) const
{
upload((void*) file_data.data(), file_data.channels() == 4 ? GL_RGBA : GL_RGB, 0, 0, 0, file_data.width(), file_data.height());
}
void blt::gfx::texture_gl2D::upload(void* data, int width, int height, GLint dataColorMode, GLint dataMode)
{
bind();
glTexImage2D(textureBindType, 0, textureColorMode, width, height, 0, dataColorMode, dataMode, data);
generateMipmaps();
unbind();
}
void blt::gfx::gl_texture2D_array::upload(void* data, int index, GLint dataColorMode, int level, int x_offset, int y_offset, int sub_width, void blt::gfx::gl_texture2D_array::upload(void* data, int index, GLint dataColorMode, int level, int x_offset, int y_offset, int sub_width,
int sub_height) const int sub_height) const
{ {