mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 21:10:04 +00:00
Create a text shader and font utility
This commit is contained in:
parent
817a59f741
commit
82b265b6d4
11 changed files with 473 additions and 5 deletions
|
|
@ -13,6 +13,7 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
include(${PROJECT_SOURCE_DIR}/external/cmake-conan/conan.cmake)
|
include(${PROJECT_SOURCE_DIR}/external/cmake-conan/conan.cmake)
|
||||||
|
|
||||||
conan_cmake_configure(REQUIRES boost/1.76.0
|
conan_cmake_configure(REQUIRES boost/1.76.0
|
||||||
|
freetype/2.10.4
|
||||||
geographiclib/1.52
|
geographiclib/1.52
|
||||||
glm/0.9.9.8
|
glm/0.9.9.8
|
||||||
gtest/cci.20210126
|
gtest/cci.20210126
|
||||||
|
|
|
||||||
12
scwx-qt/gl/text.frag
Normal file
12
scwx-qt/gl/text.frag
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#version 330 core
|
||||||
|
in vec2 texCoords;
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
uniform sampler2D text;
|
||||||
|
uniform vec4 textColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 sampled = vec4(1.0f, 1.0f, 1.0f, texture(text, texCoords).r);
|
||||||
|
color = textColor * sampled;
|
||||||
|
}
|
||||||
11
scwx-qt/gl/text.vert
Normal file
11
scwx-qt/gl/text.vert
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec4 vertex;
|
||||||
|
out vec2 texCoords;
|
||||||
|
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projection * vec4(vertex.xy, 0.0f, 1.0f);
|
||||||
|
texCoords = vertex.zw;
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
find_package(Boost)
|
find_package(Boost)
|
||||||
|
find_package(Freetype)
|
||||||
find_package(geographiclib)
|
find_package(geographiclib)
|
||||||
find_package(glm)
|
find_package(glm)
|
||||||
|
|
||||||
|
|
@ -51,6 +52,8 @@ set(HDR_MAIN source/scwx/qt/main/main_window.hpp)
|
||||||
set(SRC_MAIN source/scwx/qt/main/main.cpp
|
set(SRC_MAIN source/scwx/qt/main/main.cpp
|
||||||
source/scwx/qt/main/main_window.cpp)
|
source/scwx/qt/main/main_window.cpp)
|
||||||
set(UI_MAIN source/scwx/qt/main/main_window.ui)
|
set(UI_MAIN source/scwx/qt/main/main_window.ui)
|
||||||
|
set(HDR_GL source/scwx/qt/gl/text_shader.hpp)
|
||||||
|
set(SRC_GL source/scwx/qt/gl/text_shader.cpp)
|
||||||
set(HDR_MANAGER source/scwx/qt/manager/radar_manager.hpp)
|
set(HDR_MANAGER source/scwx/qt/manager/radar_manager.hpp)
|
||||||
set(SRC_MANAGER source/scwx/qt/manager/radar_manager.cpp)
|
set(SRC_MANAGER source/scwx/qt/manager/radar_manager.cpp)
|
||||||
set(HDR_MAP source/scwx/qt/map/map_widget.hpp
|
set(HDR_MAP source/scwx/qt/map/map_widget.hpp
|
||||||
|
|
@ -61,16 +64,20 @@ set(SRC_MAP source/scwx/qt/map/map_widget.cpp
|
||||||
source/scwx/qt/map/radar_layer.cpp
|
source/scwx/qt/map/radar_layer.cpp
|
||||||
source/scwx/qt/map/radar_range_layer.cpp
|
source/scwx/qt/map/radar_range_layer.cpp
|
||||||
source/scwx/qt/map/triangle_layer.cpp)
|
source/scwx/qt/map/triangle_layer.cpp)
|
||||||
set(HDR_UTIL source/scwx/qt/util/gl.hpp
|
set(HDR_UTIL source/scwx/qt/util/font.hpp
|
||||||
|
source/scwx/qt/util/gl.hpp
|
||||||
source/scwx/qt/util/shader_program.hpp)
|
source/scwx/qt/util/shader_program.hpp)
|
||||||
set(SRC_UTIL source/scwx/qt/util/shader_program.cpp)
|
set(SRC_UTIL source/scwx/qt/util/font.cpp
|
||||||
|
source/scwx/qt/util/shader_program.cpp)
|
||||||
set(HDR_VIEW source/scwx/qt/view/radar_view.hpp)
|
set(HDR_VIEW source/scwx/qt/view/radar_view.hpp)
|
||||||
set(SRC_VIEW source/scwx/qt/view/radar_view.cpp)
|
set(SRC_VIEW source/scwx/qt/view/radar_view.cpp)
|
||||||
|
|
||||||
set(RESOURCE_FILES scwx-qt.qrc)
|
set(RESOURCE_FILES scwx-qt.qrc)
|
||||||
|
|
||||||
set(SHADER_FILES gl/radar.frag
|
set(SHADER_FILES gl/radar.frag
|
||||||
gl/radar.vert)
|
gl/radar.vert
|
||||||
|
gl/text.frag
|
||||||
|
gl/text.vert)
|
||||||
|
|
||||||
set(TS_FILES ts/scwx_en_US.ts)
|
set(TS_FILES ts/scwx_en_US.ts)
|
||||||
|
|
||||||
|
|
@ -122,6 +129,7 @@ target_link_libraries(scwx-qt PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
|
||||||
Boost::timer
|
Boost::timer
|
||||||
qmapboxgl
|
qmapboxgl
|
||||||
opengl32
|
opengl32
|
||||||
|
Freetype::Freetype
|
||||||
GeographicLib::GeographicLib
|
GeographicLib::GeographicLib
|
||||||
glm::glm
|
glm::glm
|
||||||
wxdata)
|
wxdata)
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,7 @@
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<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>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
||||||
155
scwx-qt/source/scwx/qt/gl/text_shader.cpp
Normal file
155
scwx-qt/source/scwx/qt/gl/text_shader.cpp
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
#include <scwx/qt/gl/text_shader.hpp>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace gl
|
||||||
|
{
|
||||||
|
|
||||||
|
static const std::string logPrefix_ = "[scwx::qt::gl::text_shader] ";
|
||||||
|
|
||||||
|
class TextShaderImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TextShaderImpl(OpenGLFunctions& gl) :
|
||||||
|
gl_ {gl},
|
||||||
|
projectionLocation_(GL_INVALID_INDEX),
|
||||||
|
textColorLocation_(GL_INVALID_INDEX),
|
||||||
|
vao_ {GL_INVALID_INDEX},
|
||||||
|
vbo_ {GL_INVALID_INDEX}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~TextShaderImpl() {}
|
||||||
|
|
||||||
|
OpenGLFunctions& gl_;
|
||||||
|
|
||||||
|
GLint projectionLocation_;
|
||||||
|
GLint textColorLocation_;
|
||||||
|
|
||||||
|
GLuint vao_;
|
||||||
|
GLuint vbo_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TextShader::TextShader(OpenGLFunctions& gl) :
|
||||||
|
ShaderProgram(gl), p(std::make_unique<TextShaderImpl>(gl))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
TextShader::~TextShader() = default;
|
||||||
|
|
||||||
|
TextShader::TextShader(TextShader&&) noexcept = default;
|
||||||
|
TextShader& TextShader::operator=(TextShader&&) noexcept = default;
|
||||||
|
|
||||||
|
bool TextShader::Initialize()
|
||||||
|
{
|
||||||
|
OpenGLFunctions& gl = p->gl_;
|
||||||
|
|
||||||
|
// Load and configure shader
|
||||||
|
bool success = Load(":/gl/text.vert", ":/gl/text.frag");
|
||||||
|
|
||||||
|
p->projectionLocation_ = gl.glGetUniformLocation(id(), "projection");
|
||||||
|
if (p->projectionLocation_ == -1)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Could not find projection";
|
||||||
|
}
|
||||||
|
|
||||||
|
p->textColorLocation_ = gl.glGetUniformLocation(id(), "textColor");
|
||||||
|
if (p->textColorLocation_ == -1)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Could not find textColor";
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.glGenVertexArrays(1, &p->vao_);
|
||||||
|
gl.glGenBuffers(1, &p->vbo_);
|
||||||
|
gl.glBindVertexArray(p->vao_);
|
||||||
|
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_);
|
||||||
|
gl.glBufferData(
|
||||||
|
GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, nullptr, GL_DYNAMIC_DRAW);
|
||||||
|
gl.glEnableVertexAttribArray(0);
|
||||||
|
gl.glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
||||||
|
gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
gl.glBindVertexArray(0);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextShader::RenderText(const std::string& text,
|
||||||
|
float x,
|
||||||
|
float y,
|
||||||
|
float scale,
|
||||||
|
const glm::mat4& projection,
|
||||||
|
const boost::gil::rgba8_pixel_t& color,
|
||||||
|
const std::unordered_map<char, util::Glyph>& glyphs)
|
||||||
|
{
|
||||||
|
OpenGLFunctions& gl = p->gl_;
|
||||||
|
|
||||||
|
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.glUniform4f(
|
||||||
|
p->textColorLocation_, color[0], color[1], color[2], color[3]);
|
||||||
|
|
||||||
|
gl.glActiveTexture(GL_TEXTURE0);
|
||||||
|
gl.glBindVertexArray(p->vao_);
|
||||||
|
|
||||||
|
for (auto c = text.cbegin(); c != text.cend(); c++)
|
||||||
|
{
|
||||||
|
if (glyphs.find(*c) == glyphs.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const util::Glyph& g = glyphs.at(*c);
|
||||||
|
|
||||||
|
float xpos = x + g.bearing.x * scale;
|
||||||
|
float ypos = y - (g.size.y - g.bearing.y) * scale;
|
||||||
|
|
||||||
|
float w = g.size.x * scale;
|
||||||
|
float h = g.size.y * scale;
|
||||||
|
|
||||||
|
// Glyph vertices
|
||||||
|
float vertices[6][4] = {{xpos, ypos + h, 0.0f, 0.0f},
|
||||||
|
{xpos, ypos, 0.0f, 1.0f},
|
||||||
|
{xpos + w, ypos, 1.0f, 1.0f}, //
|
||||||
|
//
|
||||||
|
{xpos, ypos + h, 0.0f, 0.0f},
|
||||||
|
{xpos + w, ypos, 1.0f, 1.0f},
|
||||||
|
{xpos + w, ypos + h, 1.0f, 0.0f}};
|
||||||
|
|
||||||
|
// Render glyph texture
|
||||||
|
gl.glBindTexture(GL_TEXTURE_2D, g.textureId);
|
||||||
|
|
||||||
|
gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_);
|
||||||
|
gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||||
|
gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
gl.glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
|
|
||||||
|
// Advance to the next glyph
|
||||||
|
x += (g.advance >> 6) * scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextShader::SetProjection(const glm::mat4& projection)
|
||||||
|
{
|
||||||
|
p->gl_.glUniformMatrix4fv(
|
||||||
|
p->projectionLocation_, 1, GL_FALSE, glm::value_ptr(projection));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextShader::SetTextColor(const boost::gil::rgba8_pixel_t color)
|
||||||
|
{
|
||||||
|
p->gl_.glUniform4f(
|
||||||
|
p->textColorLocation_, color[0], color[1], color[2], color[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace gl
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
49
scwx-qt/source/scwx/qt/gl/text_shader.hpp
Normal file
49
scwx-qt/source/scwx/qt/gl/text_shader.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <scwx/qt/util/shader_program.hpp>
|
||||||
|
#include <scwx/qt/util/font.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <boost/gil.hpp>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace gl
|
||||||
|
{
|
||||||
|
|
||||||
|
class TextShaderImpl;
|
||||||
|
|
||||||
|
class TextShader : public ShaderProgram
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TextShader(OpenGLFunctions& gl);
|
||||||
|
~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,
|
||||||
|
const std::unordered_map<char, util::Glyph>& glyphs);
|
||||||
|
void SetProjection(const glm::mat4& projection);
|
||||||
|
void SetTextColor(const boost::gil::rgba8_pixel_t color);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<TextShaderImpl> p;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gl
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
179
scwx-qt/source/scwx/qt/util/font.cpp
Normal file
179
scwx-qt/source/scwx/qt/util/font.cpp
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
#include <scwx/qt/util/font.hpp>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
|
||||||
|
static const std::string logPrefix_ = "[scwx::qt::util::font] ";
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, std::shared_ptr<Font>> fontMap_;
|
||||||
|
|
||||||
|
static FT_Library ft_ {nullptr};
|
||||||
|
static std::mutex ftMutex_;
|
||||||
|
|
||||||
|
static bool InitializeFreeType();
|
||||||
|
|
||||||
|
class FontImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit FontImpl(const std::string& resource) :
|
||||||
|
resource_(resource), fontData_(), face_ {nullptr}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~FontImpl() {}
|
||||||
|
|
||||||
|
const std::string resource_;
|
||||||
|
|
||||||
|
QByteArray fontData_;
|
||||||
|
FT_Face face_;
|
||||||
|
};
|
||||||
|
|
||||||
|
Font::Font(const std::string& resource) :
|
||||||
|
p(std::make_unique<FontImpl>(resource))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Font::~Font()
|
||||||
|
{
|
||||||
|
FT_Done_Face(p->face_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::GenerateGlyphs(OpenGLFunctions& gl,
|
||||||
|
std::unordered_map<char, Glyph>& glyphs,
|
||||||
|
unsigned int height)
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
FT_Face& face = p->face_;
|
||||||
|
|
||||||
|
// Allow single-byte texture colors
|
||||||
|
gl.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
FT_Set_Pixel_Sizes(p->face_, 0, 48);
|
||||||
|
|
||||||
|
for (unsigned char c = 0; c < 128; c++)
|
||||||
|
{
|
||||||
|
if (glyphs.find(c) != glyphs.end())
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Found glyph "
|
||||||
|
<< static_cast<uint16_t>(c) << ", skipping";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = FT_Load_Char(face, c, FT_LOAD_RENDER)) != 0)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error) << logPrefix_ << "Failed to load glyph "
|
||||||
|
<< static_cast<uint16_t>(c) << ": " << error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint texture;
|
||||||
|
gl.glGenTextures(1, &texture);
|
||||||
|
gl.glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
gl.glTexImage2D(GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_RED,
|
||||||
|
face->glyph->bitmap.width,
|
||||||
|
face->glyph->bitmap.rows,
|
||||||
|
0,
|
||||||
|
GL_RED,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
face->glyph->bitmap.buffer);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
glyphs.insert(
|
||||||
|
{c,
|
||||||
|
Glyph {
|
||||||
|
texture,
|
||||||
|
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
|
||||||
|
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
|
||||||
|
face->glyph->advance.x}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Font> Font::Create(const std::string& resource)
|
||||||
|
{
|
||||||
|
std::shared_ptr<Font> font = nullptr;
|
||||||
|
FT_Error error;
|
||||||
|
|
||||||
|
if (!InitializeFreeType())
|
||||||
|
{
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = fontMap_.find(resource);
|
||||||
|
if (it != fontMap_.end())
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile fontFile(resource.c_str());
|
||||||
|
fontFile.open(QIODevice::ReadOnly);
|
||||||
|
if (!fontFile.isOpen())
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< logPrefix_ << "Could not read font file: " << resource;
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
font = std::make_shared<Font>(resource);
|
||||||
|
font->p->fontData_ = fontFile.readAll();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock(ftMutex_);
|
||||||
|
if ((error = FT_New_Memory_Face(
|
||||||
|
ft_,
|
||||||
|
reinterpret_cast<const FT_Byte*>(font->p->fontData_.data()),
|
||||||
|
font->p->fontData_.size(),
|
||||||
|
0,
|
||||||
|
&font->p->face_)) != 0)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< logPrefix_ << "Failed to load font: " << error;
|
||||||
|
font.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (font != nullptr)
|
||||||
|
{
|
||||||
|
fontMap_.insert({resource, font});
|
||||||
|
}
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool InitializeFreeType()
|
||||||
|
{
|
||||||
|
std::scoped_lock(ftMutex_);
|
||||||
|
|
||||||
|
FT_Error error;
|
||||||
|
|
||||||
|
if (ft_ == nullptr && (error = FT_Init_FreeType(&ft_)) != 0)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< logPrefix_ << "Could not init FreeType library: " << error;
|
||||||
|
ft_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ft_ != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
51
scwx-qt/source/scwx/qt/util/font.hpp
Normal file
51
scwx-qt/source/scwx/qt/util/font.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <scwx/qt/util/gl.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Glyph
|
||||||
|
{
|
||||||
|
GLuint textureId;
|
||||||
|
glm::ivec2 size; // pixels
|
||||||
|
glm::ivec2 bearing; // pixels
|
||||||
|
GLint advance; // 1/64 pixels
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
void GenerateGlyphs(OpenGLFunctions& gl,
|
||||||
|
std::unordered_map<char, Glyph>& glyphs,
|
||||||
|
unsigned int height);
|
||||||
|
|
||||||
|
static std::shared_ptr<Font> Create(const std::string& resource);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<FontImpl> p;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace util
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
|
|
@ -147,7 +147,7 @@ bool ShaderProgram::Load(const std::string& vertexPath,
|
||||||
gl.glDeleteShader(vertexShader);
|
gl.glDeleteShader(vertexShader);
|
||||||
gl.glDeleteShader(fragmentShader);
|
gl.glDeleteShader(fragmentShader);
|
||||||
|
|
||||||
return false;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderProgram::Use() const
|
void ShaderProgram::Use() const
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class ShaderProgram
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ShaderProgram(OpenGLFunctions& gl);
|
explicit ShaderProgram(OpenGLFunctions& gl);
|
||||||
~ShaderProgram();
|
virtual ~ShaderProgram();
|
||||||
|
|
||||||
ShaderProgram(const ShaderProgram&) = delete;
|
ShaderProgram(const ShaderProgram&) = delete;
|
||||||
ShaderProgram& operator=(const ShaderProgram&) = delete;
|
ShaderProgram& operator=(const ShaderProgram&) = delete;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue