mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 16:30:05 +00:00
Cleanup unused freetype dependencies and old text rendering
This commit is contained in:
parent
a98d978cc6
commit
c2918daebf
16 changed files with 4 additions and 1044 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -10,9 +10,6 @@
|
||||||
[submodule "external/hsluv-c"]
|
[submodule "external/hsluv-c"]
|
||||||
path = external/hsluv-c
|
path = external/hsluv-c
|
||||||
url = https://github.com/hsluv/hsluv-c.git
|
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"]
|
[submodule "external/stb"]
|
||||||
path = external/stb
|
path = external/stb
|
||||||
url = https://github.com/nothings/stb.git
|
url = https://github.com/nothings/stb.git
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ class SupercellWxConan(ConanFile):
|
||||||
requires = ("boost/1.83.0",
|
requires = ("boost/1.83.0",
|
||||||
"cpr/1.10.5",
|
"cpr/1.10.5",
|
||||||
"fontconfig/2.14.2",
|
"fontconfig/2.14.2",
|
||||||
"freetype/2.13.0",
|
|
||||||
"geographiclib/2.3",
|
"geographiclib/2.3",
|
||||||
"glew/2.2.0",
|
"glew/2.2.0",
|
||||||
"glm/cci.20230113",
|
"glm/cci.20230113",
|
||||||
|
|
|
||||||
2
external/CMakeLists.txt
vendored
2
external/CMakeLists.txt
vendored
|
|
@ -6,7 +6,6 @@ set_property(DIRECTORY
|
||||||
PROPERTY CMAKE_CONFIGURE_DEPENDS
|
PROPERTY CMAKE_CONFIGURE_DEPENDS
|
||||||
aws-sdk-cpp.cmake
|
aws-sdk-cpp.cmake
|
||||||
date.cmake
|
date.cmake
|
||||||
freetype-gl.cmake
|
|
||||||
hsluv-c.cmake
|
hsluv-c.cmake
|
||||||
imgui.cmake
|
imgui.cmake
|
||||||
mapbox-gl-native.cmake
|
mapbox-gl-native.cmake
|
||||||
|
|
@ -16,7 +15,6 @@ set_property(DIRECTORY
|
||||||
|
|
||||||
include(aws-sdk-cpp.cmake)
|
include(aws-sdk-cpp.cmake)
|
||||||
include(date.cmake)
|
include(date.cmake)
|
||||||
include(freetype-gl.cmake)
|
|
||||||
include(hsluv-c.cmake)
|
include(hsluv-c.cmake)
|
||||||
include(imgui.cmake)
|
include(imgui.cmake)
|
||||||
include(mapbox-gl-native.cmake)
|
include(mapbox-gl-native.cmake)
|
||||||
|
|
|
||||||
1
external/freetype-gl
vendored
1
external/freetype-gl
vendored
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 65b746d300e1b67033795ebb794b093eeae3b4d0
|
|
||||||
121
external/freetype-gl.cmake
vendored
121
external/freetype-gl.cmake
vendored
|
|
@ -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()
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -13,8 +13,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
find_package(Boost)
|
find_package(Boost)
|
||||||
find_package(Fontconfig)
|
find_package(Fontconfig)
|
||||||
find_package(Freetype)
|
|
||||||
find_package(geographiclib)
|
find_package(geographiclib)
|
||||||
|
find_package(GLEW)
|
||||||
find_package(glm)
|
find_package(glm)
|
||||||
find_package(Python COMPONENTS Interpreter)
|
find_package(Python COMPONENTS Interpreter)
|
||||||
find_package(SQLite3)
|
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)
|
source/scwx/qt/external/stb_rect_pack.cpp)
|
||||||
set(HDR_GL source/scwx/qt/gl/gl.hpp
|
set(HDR_GL source/scwx/qt/gl/gl.hpp
|
||||||
source/scwx/qt/gl/gl_context.hpp
|
source/scwx/qt/gl/gl_context.hpp
|
||||||
source/scwx/qt/gl/shader_program.hpp
|
source/scwx/qt/gl/shader_program.hpp)
|
||||||
source/scwx/qt/gl/text_shader.hpp)
|
|
||||||
set(SRC_GL source/scwx/qt/gl/gl_context.cpp
|
set(SRC_GL source/scwx/qt/gl/gl_context.cpp
|
||||||
source/scwx/qt/gl/shader_program.cpp
|
source/scwx/qt/gl/shader_program.cpp)
|
||||||
source/scwx/qt/gl/text_shader.cpp)
|
|
||||||
set(HDR_GL_DRAW source/scwx/qt/gl/draw/draw_item.hpp
|
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/geo_line.hpp
|
||||||
source/scwx/qt/gl/draw/placefile_icons.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)
|
source/scwx/qt/ui/setup/welcome_page.cpp)
|
||||||
set(HDR_UTIL source/scwx/qt/util/color.hpp
|
set(HDR_UTIL source/scwx/qt/util/color.hpp
|
||||||
source/scwx/qt/util/file.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/geographic_lib.hpp
|
||||||
source/scwx/qt/util/imgui.hpp
|
source/scwx/qt/util/imgui.hpp
|
||||||
source/scwx/qt/util/json.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)
|
source/scwx/qt/util/tooltip.hpp)
|
||||||
set(SRC_UTIL source/scwx/qt/util/color.cpp
|
set(SRC_UTIL source/scwx/qt/util/color.cpp
|
||||||
source/scwx/qt/util/file.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/geographic_lib.cpp
|
||||||
source/scwx/qt/util/imgui.cpp
|
source/scwx/qt/util/imgui.cpp
|
||||||
source/scwx/qt/util/json.cpp
|
source/scwx/qt/util/json.cpp
|
||||||
|
|
@ -287,8 +281,6 @@ set(SHADER_FILES gl/color.frag
|
||||||
gl/map_color.vert
|
gl/map_color.vert
|
||||||
gl/radar.frag
|
gl/radar.frag
|
||||||
gl/radar.vert
|
gl/radar.vert
|
||||||
gl/text.frag
|
|
||||||
gl/text.vert
|
|
||||||
gl/texture1d.frag
|
gl/texture1d.frag
|
||||||
gl/texture1d.vert
|
gl/texture1d.vert
|
||||||
gl/texture2d.frag
|
gl/texture2d.frag
|
||||||
|
|
@ -504,8 +496,8 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets
|
||||||
qmaplibregl
|
qmaplibregl
|
||||||
$<$<CXX_COMPILER_ID:MSVC>:opengl32>
|
$<$<CXX_COMPILER_ID:MSVC>:opengl32>
|
||||||
Fontconfig::Fontconfig
|
Fontconfig::Fontconfig
|
||||||
freetype-gl
|
|
||||||
GeographicLib::GeographicLib
|
GeographicLib::GeographicLib
|
||||||
|
GLEW::GLEW
|
||||||
glm::glm
|
glm::glm
|
||||||
imgui
|
imgui
|
||||||
SQLite::SQLite3
|
SQLite::SQLite3
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@
|
||||||
<file>gl/map_color.vert</file>
|
<file>gl/map_color.vert</file>
|
||||||
<file>gl/radar.frag</file>
|
<file>gl/radar.frag</file>
|
||||||
<file>gl/radar.vert</file>
|
<file>gl/radar.vert</file>
|
||||||
<file>gl/text.frag</file>
|
|
||||||
<file>gl/text.vert</file>
|
|
||||||
<file>gl/texture1d.frag</file>
|
<file>gl/texture1d.frag</file>
|
||||||
<file>gl/texture1d.vert</file>
|
<file>gl/texture1d.vert</file>
|
||||||
<file>gl/texture2d.frag</file>
|
<file>gl/texture2d.frag</file>
|
||||||
|
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
#include <scwx/qt/gl/text_shader.hpp>
|
|
||||||
#include <scwx/qt/gl/shader_program.hpp>
|
|
||||||
#include <scwx/util/logger.hpp>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
# pragma warning(push, 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
#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<GlContext> context) :
|
|
||||||
context_ {context},
|
|
||||||
shaderProgram_ {nullptr},
|
|
||||||
projectionLocation_(GL_INVALID_INDEX)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~TextShaderImpl() {}
|
|
||||||
|
|
||||||
std::shared_ptr<GlContext> context_;
|
|
||||||
std::shared_ptr<ShaderProgram> shaderProgram_;
|
|
||||||
|
|
||||||
GLint projectionLocation_;
|
|
||||||
};
|
|
||||||
|
|
||||||
TextShader::TextShader(std::shared_ptr<GlContext> context) :
|
|
||||||
p(std::make_unique<TextShaderImpl>(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<util::Font> 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<util::FontBuffer> buffer =
|
|
||||||
std::make_shared<util::FontBuffer>();
|
|
||||||
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
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <scwx/qt/gl/gl_context.hpp>
|
|
||||||
#include <scwx/qt/util/font.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <boost/gil.hpp>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
namespace scwx
|
|
||||||
{
|
|
||||||
namespace qt
|
|
||||||
{
|
|
||||||
namespace gl
|
|
||||||
{
|
|
||||||
|
|
||||||
enum class TextAlign
|
|
||||||
{
|
|
||||||
Left,
|
|
||||||
Center,
|
|
||||||
Right
|
|
||||||
};
|
|
||||||
|
|
||||||
class TextShaderImpl;
|
|
||||||
|
|
||||||
class TextShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit TextShader(std::shared_ptr<GlContext> 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<util::Font> font,
|
|
||||||
GLuint textureId,
|
|
||||||
TextAlign align = TextAlign::Left);
|
|
||||||
void SetProjection(const glm::mat4& projection);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<TextShaderImpl> p;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace gl
|
|
||||||
} // namespace qt
|
|
||||||
} // namespace scwx
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include <scwx/qt/map/overlay_layer.hpp>
|
#include <scwx/qt/map/overlay_layer.hpp>
|
||||||
#include <scwx/qt/gl/draw/rectangle.hpp>
|
#include <scwx/qt/gl/draw/rectangle.hpp>
|
||||||
#include <scwx/qt/gl/shader_program.hpp>
|
#include <scwx/qt/gl/shader_program.hpp>
|
||||||
#include <scwx/qt/gl/text_shader.hpp>
|
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
#include <scwx/util/time.hpp>
|
#include <scwx/util/time.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 <scwx/qt/util/font.hpp>
|
|
||||||
#include <scwx/qt/model/imgui_context_model.hpp>
|
|
||||||
#include <scwx/qt/settings/general_settings.hpp>
|
|
||||||
#include <scwx/util/logger.hpp>
|
|
||||||
|
|
||||||
#include <codecvt>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include <boost/timer/timer.hpp>
|
|
||||||
#include <fmt/format.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QFileInfo>
|
|
||||||
|
|
||||||
#include <ft2build.h>
|
|
||||||
#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 <freetype-gl.h> (exclude opengl.h)
|
|
||||||
#include <platform.h>
|
|
||||||
#include <vec234.h>
|
|
||||||
#include <vector.h>
|
|
||||||
#include <texture-atlas.h>
|
|
||||||
#include <texture-font.h>
|
|
||||||
#include <ftgl-utils.h>
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
# pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
# pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
# include <WinSock2.h>
|
|
||||||
#else
|
|
||||||
# include <arpa/inet.h>
|
|
||||||
#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<std::string, std::shared_ptr<Font>> 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<char, TextureGlyph> glyphs_;
|
|
||||||
std::unordered_map<size_t, ImFont*> imGuiFonts_;
|
|
||||||
};
|
|
||||||
|
|
||||||
Font::Font(const std::string& resource) :
|
|
||||||
p(std::make_unique<FontImpl>(resource))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
Font::~Font() = default;
|
|
||||||
|
|
||||||
float Font::BufferText(std::shared_ptr<FontBuffer> 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<uint32_t>(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<uint32_t>(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<GLsizei>(p->atlas_->width),
|
|
||||||
static_cast<GLsizei>(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> Font::Create(const std::string& resource)
|
|
||||||
{
|
|
||||||
logger_->debug("Loading font file: {}", resource);
|
|
||||||
|
|
||||||
std::shared_ptr<Font> 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<Font>(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<int>(glyph->width),
|
|
||||||
static_cast<int>(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<std::codecvt_utf8_utf16<char16_t>, 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<char*>(sfntName.string),
|
|
||||||
sfntName.string_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
} // namespace qt
|
|
||||||
} // namespace scwx
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <scwx/qt/gl/gl.hpp>
|
|
||||||
#include <scwx/qt/util/font_buffer.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <boost/gil/typedefs.hpp>
|
|
||||||
|
|
||||||
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<FontBuffer> 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<Font> Create(const std::string& resource);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<FontImpl> p;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
} // namespace qt
|
|
||||||
} // namespace scwx
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
#include <scwx/qt/util/font_buffer.hpp>
|
|
||||||
#include <scwx/util/logger.hpp>
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
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<const GLvoid*>(3 * sizeof(float)));
|
|
||||||
|
|
||||||
// vec4 aColor
|
|
||||||
gl.glEnableVertexAttribArray(2);
|
|
||||||
gl.glVertexAttribPointer(
|
|
||||||
2,
|
|
||||||
4,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
9 * sizeof(float),
|
|
||||||
reinterpret_cast<const GLvoid*>(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<GLsizei>(vertices_.size() * sizeof(GLfloat));
|
|
||||||
GLsizei iSize = static_cast<GLsizei>(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<GLfloat> vertices_;
|
|
||||||
std::vector<GLuint> indices_;
|
|
||||||
|
|
||||||
std::mutex mutex_;
|
|
||||||
};
|
|
||||||
|
|
||||||
FontBuffer::FontBuffer() : p(std::make_unique<FontBufferImpl>()) {}
|
|
||||||
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<GLuint> indices,
|
|
||||||
std::initializer_list<GLfloat> 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<GLuint>(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<GLsizei>(p->indices_.size()),
|
|
||||||
GL_UNSIGNED_INT,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
} // namespace qt
|
|
||||||
} // namespace scwx
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <scwx/qt/gl/gl.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
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<GLuint> indices,
|
|
||||||
std::initializer_list<GLfloat> vertices);
|
|
||||||
void Render(gl::OpenGLFunctions& gl);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<FontBufferImpl> p;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
} // namespace qt
|
|
||||||
} // namespace scwx
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue