diff --git a/.gitmodules b/.gitmodules index bfaddd87..8e51fe86 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,9 +10,6 @@ [submodule "external/hsluv-c"] path = external/hsluv-c url = https://github.com/hsluv/hsluv-c.git -[submodule "external/freetype-gl"] - path = external/freetype-gl - url = https://github.com/rougier/freetype-gl.git [submodule "external/stb"] path = external/stb url = https://github.com/nothings/stb.git diff --git a/conanfile.py b/conanfile.py index d86d8380..0672dee7 100644 --- a/conanfile.py +++ b/conanfile.py @@ -5,7 +5,6 @@ class SupercellWxConan(ConanFile): requires = ("boost/1.83.0", "cpr/1.10.5", "fontconfig/2.14.2", - "freetype/2.13.0", "geographiclib/2.3", "glew/2.2.0", "glm/cci.20230113", diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 3c0be1cf..8bbdf6da 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -6,7 +6,6 @@ set_property(DIRECTORY PROPERTY CMAKE_CONFIGURE_DEPENDS aws-sdk-cpp.cmake date.cmake - freetype-gl.cmake hsluv-c.cmake imgui.cmake mapbox-gl-native.cmake @@ -16,7 +15,6 @@ set_property(DIRECTORY include(aws-sdk-cpp.cmake) include(date.cmake) -include(freetype-gl.cmake) include(hsluv-c.cmake) include(imgui.cmake) include(mapbox-gl-native.cmake) diff --git a/external/freetype-gl b/external/freetype-gl deleted file mode 160000 index 65b746d3..00000000 --- a/external/freetype-gl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 65b746d300e1b67033795ebb794b093eeae3b4d0 diff --git a/external/freetype-gl.cmake b/external/freetype-gl.cmake deleted file mode 100644 index d1ea9e14..00000000 --- a/external/freetype-gl.cmake +++ /dev/null @@ -1,121 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -set(PROJECT_NAME scwx-freetype-gl) - -find_package(OpenGL REQUIRED) -find_package(Freetype REQUIRED) -find_package(GLEW REQUIRED) - -set(freetype-gl_WITH_GLEW ON) -set(freetype-gl_WITH_GLAD OFF) -set(freetype-gl_USE_VAO ON) -set(freetype-gl_BUILD_DEMOS OFF) -set(freetype-gl_BUILD_APIDOC OFF) -set(freetype-gl_BUILD_HARFBUZZ OFF) -set(freetype-gl_BUILD_MAKEFONT ON) -set(freetype-gl_BUILD_TESTS OFF) -set(freetype-gl_BUILD_SHARED OFF) -set(freetype-gl_OFF_SCREEN OFF) - -configure_file(freetype-gl/cmake/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/freetype-gl/config.h) - -set(FREETYPE_GL_HDR freetype-gl/distance-field.h - freetype-gl/edtaa3func.h - freetype-gl/font-manager.h - freetype-gl/freetype-gl.h - freetype-gl/markup.h - freetype-gl/opengl.h - freetype-gl/platform.h - freetype-gl/text-buffer.h - freetype-gl/texture-atlas.h - freetype-gl/texture-font.h - freetype-gl/utf8-utils.h - freetype-gl/ftgl-utils.h - freetype-gl/vec234.h - freetype-gl/vector.h - freetype-gl/vertex-attribute.h - freetype-gl/vertex-buffer.h - freetype-gl/freetype-gl-errdef.h - ${CMAKE_CURRENT_BINARY_DIR}/freetype-gl/config.h) -set(FREETYPE_GL_SRC freetype-gl/distance-field.c - freetype-gl/edtaa3func.c - freetype-gl/font-manager.c - freetype-gl/platform.c - freetype-gl/text-buffer.c - freetype-gl/texture-atlas.c - freetype-gl/texture-font.c - freetype-gl/utf8-utils.c - freetype-gl/ftgl-utils.c - freetype-gl/vector.c - freetype-gl/vertex-attribute.c - freetype-gl/vertex-buffer.c) - -include(CheckLibraryExists) -check_library_exists(m cos "" HAVE_MATH_LIBRARY) - -if(HAVE_MATH_LIBRARY) - list(APPEND CMAKE_REQUIRED_LIBRARIES m) - set(MATH_LIBRARY m) -endif() - -if(freetype-gl_BUILD_APIDOC) - add_subdirectory(freetype-gl/doc) -endif() - -if(freetype-gl_BUILD_SHARED) - add_library(freetype-gl SHARED ${FREETYPE_GL_SRC} - ${FREETYPE_GL_HDR}) - set_target_properties(freetype-gl PROPERTIES VERSION 0.3.2 SOVERSION 0) - target_link_libraries(freetype-gl PRIVATE opengl::opengl - Freetype::Freetype - ${MATH_LIBRARY} - GLEW::GLEW) -else() - add_library(freetype-gl STATIC ${FREETYPE_GL_SRC} - ${FREETYPE_GL_HDR}) - target_link_libraries(freetype-gl PUBLIC opengl::opengl - Freetype::Freetype - ${MATH_LIBRARY} - GLEW::GLEW) -endif() - -if(freetype-gl_BUILD_MAKEFONT) - add_executable(makefont freetype-gl/makefont.c) - target_link_libraries(makefont freetype-gl - GLEW::GLEW) -endif() - -if(freetype-gl_USE_VAO) - target_compile_definitions(freetype-gl PRIVATE FREETYPE_GL_USE_VAO) - target_compile_definitions(makefont PRIVATE FREETYPE_GL_USE_VAO) -endif() - -if(freetype-gl_USE_WITH_GLAD) - target_compile_definitions(freetype-gl PRIVATE GL_WITH_GLAD) - target_compile_definitions(makefont PRIVATE GL_WITH_GLAD) -endif() - -if(freetype-gl_USE_WITH_GLEW) - target_compile_definitions(freetype-gl PRIVATE FREETYPE_GL_USE_GLEW) - target_compile_definitions(makefont PRIVATE FREETYPE_GL_USE_GLEW) -endif() - -if(MSVC) - target_compile_definitions(freetype-gl PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE) - target_compile_definitions(makefont PRIVATE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE) -endif(MSVC) - -target_include_directories(freetype-gl PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/freetype-gl) -target_include_directories(makefont PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/freetype-gl) - -set(FTGL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/freetype-gl PARENT_SCOPE) - -set_target_properties(makefont PROPERTIES EXCLUDE_FROM_ALL True) - -set_target_properties(freetype-gl PROPERTIES FOLDER ftgl) -set_target_properties(makefont PROPERTIES FOLDER ftgl) - -if(freetype-gl_BUILD_APIDOC) - set_target_properties(doc PROPERTIES EXCLUDE_FROM_ALL True) - set_target_properties(doc PROPERTIES FOLDER ftgl) -endif() diff --git a/scwx-qt/gl/text.frag b/scwx-qt/gl/text.frag deleted file mode 100644 index bb4789a0..00000000 --- a/scwx-qt/gl/text.frag +++ /dev/null @@ -1,17 +0,0 @@ -#version 330 core - -in vec2 texCoords; -in vec4 textColor; - -out vec4 color; - -uniform sampler2D uTexture; - -void main() -{ - float dist = texture(uTexture, texCoords).r; - float width = fwidth(dist); - float alpha = smoothstep(0.5f - width, 0.5f + width, dist); - - color = vec4(textColor.rgb, textColor.a * alpha); -} diff --git a/scwx-qt/gl/text.vert b/scwx-qt/gl/text.vert deleted file mode 100644 index 9e14e429..00000000 --- a/scwx-qt/gl/text.vert +++ /dev/null @@ -1,17 +0,0 @@ -#version 330 core - -layout (location = 0) in vec3 aVertex; -layout (location = 1) in vec2 aTexCoords; -layout (location = 2) in vec4 aColor; - -out vec2 texCoords; -out vec4 textColor; - -uniform mat4 projection; - -void main() -{ - gl_Position = projection * vec4(aVertex, 1.0f); - texCoords = aTexCoords; - textColor = aColor; -} diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index bf1a57ff..e6f55544 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -13,8 +13,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Boost) find_package(Fontconfig) -find_package(Freetype) find_package(geographiclib) +find_package(GLEW) find_package(glm) find_package(Python COMPONENTS Interpreter) find_package(SQLite3) @@ -51,11 +51,9 @@ set(SRC_EXTERNAL source/scwx/qt/external/stb_image.cpp source/scwx/qt/external/stb_rect_pack.cpp) set(HDR_GL source/scwx/qt/gl/gl.hpp source/scwx/qt/gl/gl_context.hpp - source/scwx/qt/gl/shader_program.hpp - source/scwx/qt/gl/text_shader.hpp) + source/scwx/qt/gl/shader_program.hpp) set(SRC_GL source/scwx/qt/gl/gl_context.cpp - source/scwx/qt/gl/shader_program.cpp - source/scwx/qt/gl/text_shader.cpp) + source/scwx/qt/gl/shader_program.cpp) set(HDR_GL_DRAW source/scwx/qt/gl/draw/draw_item.hpp source/scwx/qt/gl/draw/geo_line.hpp source/scwx/qt/gl/draw/placefile_icons.hpp @@ -238,8 +236,6 @@ set(SRC_UI_SETUP source/scwx/qt/ui/setup/finish_page.cpp source/scwx/qt/ui/setup/welcome_page.cpp) set(HDR_UTIL source/scwx/qt/util/color.hpp source/scwx/qt/util/file.hpp - source/scwx/qt/util/font.hpp - source/scwx/qt/util/font_buffer.hpp source/scwx/qt/util/geographic_lib.hpp source/scwx/qt/util/imgui.hpp source/scwx/qt/util/json.hpp @@ -253,8 +249,6 @@ set(HDR_UTIL source/scwx/qt/util/color.hpp source/scwx/qt/util/tooltip.hpp) set(SRC_UTIL source/scwx/qt/util/color.cpp source/scwx/qt/util/file.cpp - source/scwx/qt/util/font.cpp - source/scwx/qt/util/font_buffer.cpp source/scwx/qt/util/geographic_lib.cpp source/scwx/qt/util/imgui.cpp source/scwx/qt/util/json.cpp @@ -287,8 +281,6 @@ set(SHADER_FILES gl/color.frag gl/map_color.vert gl/radar.frag gl/radar.vert - gl/text.frag - gl/text.vert gl/texture1d.frag gl/texture1d.vert gl/texture2d.frag @@ -504,8 +496,8 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets qmaplibregl $<$:opengl32> Fontconfig::Fontconfig - freetype-gl GeographicLib::GeographicLib + GLEW::GLEW glm::glm imgui SQLite::SQLite3 diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc index bc9e8b7a..298ef828 100644 --- a/scwx-qt/scwx-qt.qrc +++ b/scwx-qt/scwx-qt.qrc @@ -7,8 +7,6 @@ gl/map_color.vert gl/radar.frag gl/radar.vert - gl/text.frag - gl/text.vert gl/texture1d.frag gl/texture1d.vert gl/texture2d.frag diff --git a/scwx-qt/source/scwx/qt/gl/text_shader.cpp b/scwx-qt/source/scwx/qt/gl/text_shader.cpp deleted file mode 100644 index c349597f..00000000 --- a/scwx-qt/source/scwx/qt/gl/text_shader.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include -#include -#include - -#if defined(_MSC_VER) -# pragma warning(push, 0) -#endif - -#include - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -namespace scwx -{ -namespace qt -{ -namespace gl -{ - -static const std::string logPrefix_ = "scwx::qt::gl::text_shader"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class TextShaderImpl -{ -public: - explicit TextShaderImpl(std::shared_ptr context) : - context_ {context}, - shaderProgram_ {nullptr}, - projectionLocation_(GL_INVALID_INDEX) - { - } - - ~TextShaderImpl() {} - - std::shared_ptr context_; - std::shared_ptr shaderProgram_; - - GLint projectionLocation_; -}; - -TextShader::TextShader(std::shared_ptr context) : - p(std::make_unique(context)) -{ -} -TextShader::~TextShader() = default; - -TextShader::TextShader(TextShader&&) noexcept = default; -TextShader& TextShader::operator=(TextShader&&) noexcept = default; - -bool TextShader::Initialize() -{ - OpenGLFunctions& gl = p->context_->gl(); - - // Load and configure shader - p->shaderProgram_ = - p->context_->GetShaderProgram(":/gl/text.vert", ":/gl/text.frag"); - - p->projectionLocation_ = - gl.glGetUniformLocation(p->shaderProgram_->id(), "projection"); - if (p->projectionLocation_ == -1) - { - logger_->warn("Could not find projection"); - } - - return true; -} - -void TextShader::RenderText(const std::string& text, - float x, - float y, - float pointSize, - const glm::mat4& projection, - const boost::gil::rgba8_pixel_t& color, - std::shared_ptr font, - GLuint textureId, - TextAlign align) -{ - OpenGLFunctions& gl = p->context_->gl(); - - p->shaderProgram_->Use(); - - gl.glEnable(GL_BLEND); - gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - gl.glUniformMatrix4fv( - p->projectionLocation_, 1, GL_FALSE, glm::value_ptr(projection)); - - gl.glActiveTexture(GL_TEXTURE0); - gl.glBindTexture(GL_TEXTURE_2D, textureId); - - switch (align) - { - case TextAlign::Left: - // Do nothing - break; - - case TextAlign::Center: - // X position is the center of text, subtract half length - x -= font->TextLength(text, pointSize) * 0.5f; - break; - - case TextAlign::Right: - // X position is the end of text, subtract length - x -= font->TextLength(text, pointSize); - break; - } - - std::shared_ptr buffer = - std::make_shared(); - font->BufferText(buffer, text, x, y, pointSize, color); - buffer->Render(gl); -} - -void TextShader::SetProjection(const glm::mat4& projection) -{ - p->context_->gl().glUniformMatrix4fv( - p->projectionLocation_, 1, GL_FALSE, glm::value_ptr(projection)); -} - -} // namespace gl -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/gl/text_shader.hpp b/scwx-qt/source/scwx/qt/gl/text_shader.hpp deleted file mode 100644 index ed81907a..00000000 --- a/scwx-qt/source/scwx/qt/gl/text_shader.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace gl -{ - -enum class TextAlign -{ - Left, - Center, - Right -}; - -class TextShaderImpl; - -class TextShader -{ -public: - explicit TextShader(std::shared_ptr context); - ~TextShader(); - - TextShader(const TextShader&) = delete; - TextShader& operator=(const TextShader&) = delete; - - TextShader(TextShader&&) noexcept; - TextShader& operator=(TextShader&&) noexcept; - - bool Initialize(); - void RenderText(const std::string& text, - float x, - float y, - float scale, - const glm::mat4& projection, - const boost::gil::rgba8_pixel_t& color, - std::shared_ptr font, - GLuint textureId, - TextAlign align = TextAlign::Left); - void SetProjection(const glm::mat4& projection); - -private: - std::unique_ptr p; -}; - -} // namespace gl -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp index d114573d..75526ba6 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include diff --git a/scwx-qt/source/scwx/qt/util/font.cpp b/scwx-qt/source/scwx/qt/util/font.cpp deleted file mode 100644 index f2397bd2..00000000 --- a/scwx-qt/source/scwx/qt/util/font.cpp +++ /dev/null @@ -1,408 +0,0 @@ -// No suitable standard C++ replacement -#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING - -// Disable strncpy warning -#define _CRT_SECURE_NO_WARNINGS - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include FT_FREETYPE_H -#include FT_SFNT_NAMES_H -#include FT_TRUETYPE_IDS_H - -#if defined(_MSC_VER) -# pragma warning(push, 0) -#endif - -#if defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpedantic" -#endif - -// #include (exclude opengl.h) -#include -#include -#include -#include -#include -#include - -#if defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -#ifdef WIN32 -# include -#else -# include -#endif - -namespace scwx -{ -namespace qt -{ -namespace util -{ - -struct TextureGlyph -{ - int offsetX_; - int offsetY_; - int width_; - int height_; - float s0_; - float t0_; - float s1_; - float t1_; - float advanceX_; - - TextureGlyph(int offsetX, - int offsetY, - int width, - int height, - float s0, - float t0, - float s1, - float t1, - float advanceX) : - offsetX_ {offsetX}, - offsetY_ {offsetY}, - width_ {width}, - height_ {height}, - s0_ {s0}, - t0_ {t0}, - s1_ {s1}, - t1_ {t1}, - advanceX_ {advanceX} - { - } -}; - -static const std::string CODEPOINTS = - " !\"#$%&'()*+,-./0123456789:;<=>?" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" - "`abcdefghijklmnopqrstuvwxyz{|}~"; - -static const std::string logPrefix_ = "scwx::qt::util::font"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -static constexpr float BASE_POINT_SIZE = 72.0f; -static constexpr float POINT_SCALE = 1.0f / BASE_POINT_SIZE; - -static std::unordered_map> fontMap_; - -static void ParseSfntName(const FT_SfntName& sfntName, std::string& str); - -class FontImpl -{ -public: - explicit FontImpl(const std::string& resource) : - resource_(resource), atlas_ {nullptr} - { - } - - ~FontImpl() - { - if (atlas_ != nullptr) - { - ftgl::texture_atlas_delete(atlas_); - } - } - - void ParseNames(FT_Face face); - - const std::string resource_; - - struct - { - std::string fontFamily_; - std::string fontSubfamily_; - } fontData_; - - ftgl::texture_atlas_t* atlas_; - std::unordered_map glyphs_; - std::unordered_map imGuiFonts_; -}; - -Font::Font(const std::string& resource) : - p(std::make_unique(resource)) -{ -} -Font::~Font() = default; - -float Font::BufferText(std::shared_ptr buffer, - const std::string& text, - float x, - float y, - float pointSize, - boost::gil::rgba8_pixel_t color) const -{ - static constexpr float colorScale = 1.0f / 255.0f; - - const float scale = pointSize * POINT_SCALE; - - float r = color[0] * colorScale; - float g = color[1] * colorScale; - float b = color[2] * colorScale; - float a = color[3] * colorScale; - - for (size_t i = 0; i < text.length(); ++i) - { - const char& c = text[i]; - - auto it = p->glyphs_.find(c); - if (it == p->glyphs_.end()) - { - logger_->info("Could not draw character: {}", - static_cast(c)); - continue; - } - - TextureGlyph& glyph = it->second; - - if (i > 0) - { - x += Kerning(text[i - 1], c) * scale; - } - - float x0 = x + glyph.offsetX_ * scale; - float y0 = y + glyph.offsetY_ * scale; - float x1 = x0 + glyph.width_ * scale; - float y1 = y0 - glyph.height_ * scale; - - float s0 = glyph.s0_; - float t0 = glyph.t0_; - float s1 = glyph.s1_; - float t1 = glyph.t1_; - - buffer->Push(/* Indices */ {0, 1, 2, 0, 2, 3}, // - /* Vertices */ {x0, y0, 0, s0, t0, r, g, b, a, // - x0, y1, 0, s0, t1, r, g, b, a, // - x1, y1, 0, s1, t1, r, g, b, a, // - x1, y0, 0, s1, t0, r, g, b, a}); - - x += glyph.advanceX_ * scale; - } - - return x; -} - -float Font::Kerning(char /*c1*/, char /*c2*/) const -{ - // TODO - return 0.0f; -} - -float Font::TextLength(const std::string& text, float pointSize) const -{ - const float scale = pointSize * POINT_SCALE; - - float x = 0.0f; - - for (size_t i = 0; i < text.length(); ++i) - { - const char& c = text[i]; - - auto it = p->glyphs_.find(c); - if (it == p->glyphs_.end()) - { - logger_->info("Character not found: {}", static_cast(c)); - continue; - } - - TextureGlyph& glyph = it->second; - - if (i > 0) - { - x += Kerning(text[i - 1], c) * scale; - } - - x += glyph.advanceX_ * scale; - } - - return x; -} - -GLuint Font::GenerateTexture(gl::OpenGLFunctions& gl) -{ - gl.glGenTextures(1, &p->atlas_->id); - gl.glBindTexture(GL_TEXTURE_2D, p->atlas_->id); - - gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gl.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - gl.glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RED, - static_cast(p->atlas_->width), - static_cast(p->atlas_->height), - 0, - GL_RED, - GL_UNSIGNED_BYTE, - p->atlas_->data); - - return p->atlas_->id; -} - -ImFont* Font::ImGuiFont(std::size_t fontPixelSize) -{ - auto it = p->imGuiFonts_.find(fontPixelSize); - if (it != p->imGuiFonts_.cend()) - { - return it->second; - } - return nullptr; -} - -std::shared_ptr Font::Create(const std::string& resource) -{ - logger_->debug("Loading font file: {}", resource); - - std::shared_ptr font = nullptr; - boost::timer::cpu_timer timer; - - auto it = fontMap_.find(resource); - if (it != fontMap_.end()) - { - logger_->debug("Font already created"); - return it->second; - } - - QFile fontFile(resource.c_str()); - fontFile.open(QIODevice::ReadOnly); - if (!fontFile.isOpen()) - { - logger_->error("Could not read font file"); - return font; - } - - font = std::make_shared(resource); - QByteArray fontData = fontFile.readAll(); - - font->p->atlas_ = ftgl::texture_atlas_new(512, 512, 1); - ftgl::texture_font_t* textureFont = ftgl::texture_font_new_from_memory( - font->p->atlas_, BASE_POINT_SIZE, fontData.constData(), fontData.size()); - - font->p->ParseNames(textureFont->face); - - textureFont->rendermode = ftgl::RENDER_SIGNED_DISTANCE_FIELD; - - timer.start(); - texture_font_load_glyphs(textureFont, CODEPOINTS.c_str()); - timer.stop(); - - // Single-byte UTF-8 characters - for (const char& c : CODEPOINTS) - { - const ftgl::texture_glyph_t* glyph = - ftgl::texture_font_get_glyph(textureFont, &c); - - if (glyph != nullptr) - { - font->p->glyphs_.emplace(c, - TextureGlyph(glyph->offset_x, - glyph->offset_y, - static_cast(glyph->width), - static_cast(glyph->height), - glyph->s0, - glyph->t0, - glyph->s1, - glyph->t1, - glyph->advance_x)); - } - } - - logger_->debug("Font loaded in {}", timer.format(6, "%ws")); - - texture_font_delete(textureFont); - - if (font != nullptr) - { - fontMap_.insert({resource, font}); - } - - return font; -} - -void FontImpl::ParseNames(FT_Face face) -{ - FT_SfntName sfntName; - FT_Error error; - - FT_UInt nameCount = FT_Get_Sfnt_Name_Count(face); - - for (FT_UInt i = 0; i < nameCount; i++) - { - error = FT_Get_Sfnt_Name(face, i, &sfntName); - - if (error == 0) - { - switch (sfntName.name_id) - { - case TT_NAME_ID_FONT_FAMILY: - ParseSfntName(sfntName, fontData_.fontFamily_); - break; - - case TT_NAME_ID_FONT_SUBFAMILY: - ParseSfntName(sfntName, fontData_.fontSubfamily_); - break; - } - } - } - - logger_->debug( - "Font family: {} ({})", fontData_.fontFamily_, fontData_.fontSubfamily_); -} - -static void ParseSfntName(const FT_SfntName& sfntName, std::string& str) -{ - if (str.empty()) - { - if (sfntName.platform_id == TT_PLATFORM_MICROSOFT && - sfntName.encoding_id == TT_MS_ID_UNICODE_CS) - { - char16_t* tempString = new char16_t[sfntName.string_len / 2]; - memcpy(tempString, sfntName.string, sfntName.string_len); - - for (size_t j = 0; j < sfntName.string_len / 2; j++) - { - tempString[j] = ntohs(tempString[j]); - } - - str = - std::wstring_convert, char16_t> {} - .to_bytes(tempString, tempString + sfntName.string_len / 2); - - delete[] tempString; - } - else if (sfntName.platform_id == TT_PLATFORM_MACINTOSH && - sfntName.encoding_id == TT_MAC_ID_ROMAN) - { - str = std::string(reinterpret_cast(sfntName.string), - sfntName.string_len); - } - } -} - -} // namespace util -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/font.hpp b/scwx-qt/source/scwx/qt/util/font.hpp deleted file mode 100644 index f545a93b..00000000 --- a/scwx-qt/source/scwx/qt/util/font.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -#include - -struct ImFont; - -namespace scwx -{ -namespace qt -{ -namespace util -{ - -class FontImpl; - -class Font -{ -public: - explicit Font(const std::string& resource); - ~Font(); - - Font(const Font&) = delete; - Font& operator=(const Font&) = delete; - - Font(Font&&) = delete; - Font& operator=(Font&&) = delete; - - float BufferText(std::shared_ptr buffer, - const std::string& text, - float x, - float y, - float pointSize, - boost::gil::rgba8_pixel_t color) const; - float Kerning(char c1, char c2) const; - float TextLength(const std::string& text, float pointSize) const; - - ImFont* ImGuiFont(std::size_t fontPixelSize); - - GLuint GenerateTexture(gl::OpenGLFunctions& gl); - - static std::shared_ptr Create(const std::string& resource); - -private: - std::unique_ptr p; -}; - -} // namespace util -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/font_buffer.cpp b/scwx-qt/source/scwx/qt/util/font_buffer.cpp deleted file mode 100644 index 53e88aff..00000000 --- a/scwx-qt/source/scwx/qt/util/font_buffer.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include -#include - -#include - -namespace scwx -{ -namespace qt -{ -namespace util -{ - -static const std::string logPrefix_ = "scwx::qt::util::font_buffer"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class FontBufferImpl -{ -public: - explicit FontBufferImpl() : - vaoId_ {GL_INVALID_INDEX}, - verticesId_ {GL_INVALID_INDEX}, - indicesId_ {GL_INVALID_INDEX}, - gpuISize_ {0}, - gpuVSize_ {0}, - dirty_ {true} - { - } - - ~FontBufferImpl() {} - - void RenderSetup(gl::OpenGLFunctions& gl) - { - // Generate and setup VAO - gl.glGenVertexArrays(1, &vaoId_); - gl.glBindVertexArray(vaoId_); - - gl.glBindBuffer(GL_ARRAY_BUFFER, verticesId_); - - // vec3 aVertex - gl.glEnableVertexAttribArray(0); - gl.glVertexAttribPointer( - 0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), nullptr); - - // vec2 aTexCoords - gl.glEnableVertexAttribArray(1); - gl.glVertexAttribPointer( - 1, - 2, - GL_FLOAT, - GL_FALSE, - 9 * sizeof(float), - reinterpret_cast(3 * sizeof(float))); - - // vec4 aColor - gl.glEnableVertexAttribArray(2); - gl.glVertexAttribPointer( - 2, - 4, - GL_FLOAT, - GL_FALSE, - 9 * sizeof(float), - reinterpret_cast(5 * sizeof(float))); - - gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesId_); - } - - void Upload(gl::OpenGLFunctions& gl) - { - if (verticesId_ == GL_INVALID_INDEX) - { - gl.glGenBuffers(1, &verticesId_); - } - if (indicesId_ == GL_INVALID_INDEX) - { - gl.glGenBuffers(1, &indicesId_); - } - - GLsizei vSize = static_cast(vertices_.size() * sizeof(GLfloat)); - GLsizei iSize = static_cast(indices_.size() * sizeof(GLuint)); - - // Always upload vertices first to avoid rendering non-existent data - - // Upload vertices - gl.glBindBuffer(GL_ARRAY_BUFFER, verticesId_); - if (vSize != gpuVSize_) - { - gl.glBufferData( - GL_ARRAY_BUFFER, vSize, vertices_.data(), GL_DYNAMIC_DRAW); - gpuVSize_ = vSize; - } - else - { - gl.glBufferSubData(GL_ARRAY_BUFFER, 0, vSize, vertices_.data()); - } - - // Upload indices - gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesId_); - if (iSize != gpuISize_) - { - gl.glBufferData( - GL_ELEMENT_ARRAY_BUFFER, iSize, indices_.data(), GL_DYNAMIC_DRAW); - } - else - { - gl.glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, iSize, indices_.data()); - } - - dirty_ = false; - } - - GLuint vaoId_; - GLuint verticesId_; - GLuint indicesId_; - GLsizei gpuISize_; - GLsizei gpuVSize_; - bool dirty_; - - std::vector vertices_; - std::vector indices_; - - std::mutex mutex_; -}; - -FontBuffer::FontBuffer() : p(std::make_unique()) {} -FontBuffer::~FontBuffer() = default; - -void FontBuffer::Clear() -{ - if (!p->indices_.empty() || !p->vertices_.empty()) - { - std::scoped_lock lock(p->mutex_); - p->indices_.clear(); - p->vertices_.clear(); - p->dirty_ = true; - } -} - -void FontBuffer::Push(std::initializer_list indices, - std::initializer_list vertices) -{ - if (indices.size() % 3 != 0 || vertices.size() % 9 != 0) - { - logger_->warn("Invalid push arguments, ignoring"); - return; - } - - std::scoped_lock lock(p->mutex_); - - GLuint indexStart = static_cast(p->vertices_.size() / 9); - - for (GLuint index : indices) - { - p->indices_.push_back(index + indexStart); - } - - p->vertices_.insert(p->vertices_.end(), vertices); -} - -void FontBuffer::Render(gl::OpenGLFunctions& gl) -{ - std::scoped_lock lock(p->mutex_); - - if (p->dirty_) - { - p->Upload(gl); - } - - if (p->vaoId_ == GL_INVALID_INDEX) - { - p->RenderSetup(gl); - } - - // Bind VAO for drawing - gl.glBindVertexArray(p->vaoId_); - - gl.glDrawElements(GL_TRIANGLES, - static_cast(p->indices_.size()), - GL_UNSIGNED_INT, - 0); -} - -} // namespace util -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/font_buffer.hpp b/scwx-qt/source/scwx/qt/util/font_buffer.hpp deleted file mode 100644 index db886bc6..00000000 --- a/scwx-qt/source/scwx/qt/util/font_buffer.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -#include - -namespace scwx -{ -namespace qt -{ -namespace util -{ - -class FontBufferImpl; - -class FontBuffer -{ -public: - explicit FontBuffer(); - ~FontBuffer(); - - FontBuffer(const FontBuffer&) = delete; - FontBuffer& operator=(const FontBuffer&) = delete; - - FontBuffer(FontBuffer&&) = delete; - FontBuffer& operator=(FontBuffer&&) = delete; - - void Clear(); - void Push(std::initializer_list indices, - std::initializer_list vertices); - void Render(gl::OpenGLFunctions& gl); - -private: - std::unique_ptr p; -}; - -} // namespace util -} // namespace qt -} // namespace scwx