diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ccb838..b590688 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.25) include(FetchContent) -set(BLT_GRAPHICS_VERSION 1.0.3) +set(BLT_GRAPHICS_VERSION 1.0.4) set(BLT_GRAPHICS_TEST_VERSION 0.0.1) project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION}) diff --git a/include/blt/gfx/font/font.h b/include/blt/gfx/font/font.h index a480742..6924d39 100644 --- a/include/blt/gfx/font/font.h +++ b/include/blt/gfx/font/font.h @@ -16,8 +16,6 @@ * along with this program. If not, see . */ -#include "blt/std/types.h" - #ifndef BLT_WITH_GRAPHICS_FONT_H #define BLT_WITH_GRAPHICS_FONT_H @@ -27,6 +25,8 @@ #include #include #include +#include "blt/std/types.h" +#include namespace blt::gfx::font { @@ -49,7 +49,7 @@ namespace blt::gfx::font font_face_t& set_pixel_sizes(blt::u32 width, blt::u32 height); - std::optional load_char(char c); + [[nodiscard]] std::optional load_char(FT_ULong c) const; [[nodiscard]] FT_Face* get() const { @@ -64,9 +64,20 @@ namespace blt::gfx::font struct font_file_t { - std::string_view path; - blt::u32 character_min_index; - blt::u32 character_max_index; + font_face_t font; + blt::u64 character_min_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); }; } diff --git a/include/blt/gfx/renderer/font_renderer.h b/include/blt/gfx/renderer/font_renderer.h index 2d47725..7925615 100644 --- a/include/blt/gfx/renderer/font_renderer.h +++ b/include/blt/gfx/renderer/font_renderer.h @@ -20,16 +20,46 @@ #define BLT_WITH_GRAPHICS_FONT_RENDERER_H #include +#include +#include +#include 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 glyphs; + blt::u32 used_width = 0; + blt::u32 used_height = 0; + }; class font_renderer_t { public: - explicit font_renderer_t(); + explicit font_renderer_t(const std::vector& files, blt::i32 dimensions = 4096); + private: }; diff --git a/libraries/BLT b/libraries/BLT index 7bf24a1..05e5fcf 160000 --- a/libraries/BLT +++ b/libraries/BLT @@ -1 +1 @@ -Subproject commit 7bf24a11a53d345b58a7437a1b9768f2da78eeb2 +Subproject commit 05e5fcf7f1091d6c85711ff7ce53d840c17e547b diff --git a/src/blt/gfx/font/font.cpp b/src/blt/gfx/font/font.cpp index 73c83aa..721d72f 100644 --- a/src/blt/gfx/font/font.cpp +++ b/src/blt/gfx/font/font.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "blt/std/assert.h" namespace blt::gfx::font @@ -252,13 +253,19 @@ namespace blt::gfx::font return *this; } - std::optional font_face_t::load_char(char c) + std::optional font_face_t::load_char(FT_ULong c) const { if (int err = FT_Load_Char(*face, c, FT_LOAD_RENDER)) return {err}; 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_data[91608 / 4] = diff --git a/src/blt/gfx/renderer/font_renderer.cpp b/src/blt/gfx/renderer/font_renderer.cpp index 5164f15..8c32ec2 100644 --- a/src/blt/gfx/renderer/font_renderer.cpp +++ b/src/blt/gfx/renderer/font_renderer.cpp @@ -19,5 +19,62 @@ 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(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(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(begin_width), static_cast(begin_height), + static_cast(width), static_cast(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& files, blt::i32 dimensions) + { + + } } \ No newline at end of file diff --git a/src/blt/gfx/texture.cpp b/src/blt/gfx/texture.cpp index 3a932d2..745696e 100644 --- a/src/blt/gfx/texture.cpp +++ b/src/blt/gfx/texture.cpp @@ -180,33 +180,6 @@ void blt::gfx::texture_gl::setDefaults(GLint type, GLint wrap_type) const #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) { m_width = width; @@ -238,6 +211,34 @@ blt::gfx::texture_gl2D::texture_gl2D(const blt::gfx::texture_data& data): 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, int sub_height) const {