Continue adding opengl font support.

This commit is contained in:
James Grogan 2022-11-15 15:50:36 +00:00
parent 649079a5c7
commit eef93efc29
37 changed files with 530 additions and 157 deletions

View file

@ -51,7 +51,7 @@ In `xdg-shell-protocol.cpp` - we need access to `xdg_wm_base_interface` so expor
#### 3D Rendering #### 3D Rendering
```bash ```bash
sudo apt-get install libgl-dev libegl1-mesa-dev libglu1-mesa-dev sudo apt-get install libgl-dev libegl1-mesa-dev libglu1-mesa-dev libglm-dev
``` ```
#### fonts #### fonts

View file

@ -7,7 +7,7 @@
class Color class Color
{ {
public: public:
Color(unsigned r, unsigned g, unsigned b, double a = 1.0); Color(unsigned r = 0, unsigned g = 0, unsigned b = 0, double a = 1.0);
static std::shared_ptr<Color> CreateShared(unsigned r, unsigned g, unsigned b, double a = 1.0); static std::shared_ptr<Color> CreateShared(unsigned r, unsigned g, unsigned b, double a = 1.0);
static std::unique_ptr<Color> Create(unsigned r, unsigned g, unsigned b, double a = 1.0); static std::unique_ptr<Color> Create(unsigned r, unsigned g, unsigned b, double a = 1.0);

View file

@ -113,6 +113,22 @@ std::vector<std::string> File::readLines()
return content; return content;
} }
std::string File::read()
{
if (!PathExists())
{
return {};
}
Open(false);
std::stringstream buffer;
buffer << mInHandle->rdbuf();
Close();
return buffer.str();
}
std::string File::getBaseFilename(const Path& path) std::string File::getBaseFilename(const Path& path)
{ {
return path.stem().string(); return path.stem().string();

View file

@ -36,6 +36,8 @@ public:
std::vector<std::string> readLines(); std::vector<std::string> readLines();
std::string read();
static std::string getBaseFilename(const Path& path); static std::string getBaseFilename(const Path& path);
bool PathExists() const; bool PathExists() const;

View file

@ -3,6 +3,7 @@
#include "IFontEngine.h" #include "IFontEngine.h"
#include "Image.h" #include "Image.h"
#include "FontGlyph.h"
class BasicFontEngine : public IFontEngine class BasicFontEngine : public IFontEngine
{ {
@ -10,5 +11,5 @@ class BasicFontEngine : public IFontEngine
virtual void loadFontFace(const std::filesystem::path& fontFile, int penSize = 16){}; virtual void loadFontFace(const std::filesystem::path& fontFile, int penSize = 16){};
virtual std::unique_ptr<Image<unsigned char> > loadGlyph(unsigned charCode){return nullptr;}; virtual std::unique_ptr<FontGlyph> loadGlyph(unsigned charCode){return nullptr;};
}; };

View file

@ -5,6 +5,7 @@ list(APPEND fonts_LIB_INCLUDES
FontReader.cpp FontReader.cpp
TrueTypeFont.cpp TrueTypeFont.cpp
FontsManager.cpp FontsManager.cpp
FontGlyph.cpp
) )
if(UNIX) if(UNIX)

43
src/fonts/FontGlyph.cpp Normal file
View file

@ -0,0 +1,43 @@
#include "FontGlyph.h"
FontGlyph::FontGlyph(unsigned width, unsigned height, unsigned bearingX, unsigned bearingY,
unsigned advanceX, std::unique_ptr<Image<unsigned char> > image)
: mImage(std::move(image)),
mWidth(width),
mHeight(height),
mBearingX(mBearingX),
mBearingY(mBearingY),
mAdvanceX(mAdvanceX)
{
}
Image<unsigned char>* FontGlyph::getImage() const
{
return mImage.get();
}
unsigned FontGlyph::getWidth() const
{
return mWidth;
}
unsigned FontGlyph::getHeight() const
{
return mHeight;
}
unsigned FontGlyph::getBearingX() const
{
return mBearingX;
}
unsigned FontGlyph::getBearingY() const
{
return mBearingY;
}
unsigned FontGlyph::getAdvanceX() const
{
return mAdvanceX;
}

29
src/fonts/FontGlyph.h Normal file
View file

@ -0,0 +1,29 @@
#pragma once
#include <memory>
#include "Image.h"
class FontGlyph
{
public:
FontGlyph(unsigned width, unsigned height, unsigned bearingX, unsigned bearingY,
unsigned advanceX, std::unique_ptr<Image<unsigned char> > image);
Image<unsigned char>* getImage() const;
unsigned getWidth() const;
unsigned getHeight() const;
unsigned getBearingX() const;
unsigned getBearingY() const;
unsigned getAdvanceX() const;
private:
unsigned mWidth{0};
unsigned mHeight{0};
unsigned mBearingX{0};
unsigned mBearingY{0};
unsigned mAdvanceX{0};
std::unique_ptr<Image<unsigned char> > mImage;
};

0
src/fonts/FontItem.cpp Normal file
View file

35
src/fonts/FontItem.h Normal file
View file

@ -0,0 +1,35 @@
#pragma once
#include <filesystem>
#include <string>
class FontItem
{
public:
FontItem(const std::string& faceName = "Arial", unsigned size = 16)
: mFaceName(faceName),
mSize(size)
{
}
bool hasPath() const
{
return !mPath.empty();
}
const std::filesystem::path& getPath() const
{
return mPath;
}
void setPath(std::filesystem::path path)
{
mPath = path;
}
private:
unsigned mSize{16};
std::string mFaceName;
std::filesystem::path mPath;
};

View file

@ -3,8 +3,8 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "IFont.h"
#include "File.h" #include "File.h"
#include "IFont.h"
class File; class File;

View file

@ -20,4 +20,20 @@ IFontEngine* FontsManager::getFontEngine() const
return mFontEngine.get(); return mFontEngine.get();
} }
FontGlyph* FontsManager::getGlyph(char c)
{
auto iter = mGlyphs.find(c);
if(iter != mGlyphs.end())
{
return iter->second.get();
}
else
{
auto glyph = mFontEngine->loadGlyph(c);
auto glyph_ptr = glyph.get();
mGlyphs[c] = std::move(glyph);
return glyph_ptr;
}
}

View file

@ -2,8 +2,10 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <unordered_map>
class IFontEngine; class IFontEngine;
class FontGlyph;
class FontsManager class FontsManager
{ {
@ -13,8 +15,12 @@ public:
IFontEngine* getFontEngine() const; IFontEngine* getFontEngine() const;
FontGlyph* getGlyph(char c);
private: private:
std::unique_ptr<IFontEngine> mFontEngine; std::unique_ptr<IFontEngine> mFontEngine;
std::unordered_map<char, std::unique_ptr<FontGlyph> > mGlyphs;
}; };
using FontsManagerPtr = std::unique_ptr<FontsManager>; using FontsManagerPtr = std::unique_ptr<FontsManager>;

View file

@ -2,6 +2,7 @@
#include "Image.h" #include "Image.h"
#include "FileLogger.h" #include "FileLogger.h"
#include "FontGlyph.h"
void FreeTypeFontEngine::initialize() void FreeTypeFontEngine::initialize()
{ {
@ -37,7 +38,7 @@ void FreeTypeFontEngine::loadFontFace(const std::filesystem::path& fontFile, int
FT_Set_Pixel_Sizes(mWorkingFontFace, penSize, 0); FT_Set_Pixel_Sizes(mWorkingFontFace, penSize, 0);
} }
std::unique_ptr<Image<unsigned char> > FreeTypeFontEngine::loadGlyph(unsigned charCode) std::unique_ptr<FontGlyph> FreeTypeFontEngine::loadGlyph(unsigned charCode)
{ {
auto glyph_index = FT_Get_Char_Index( mWorkingFontFace, 65 ); auto glyph_index = FT_Get_Char_Index( mWorkingFontFace, 65 );
if (glyph_index == 0) if (glyph_index == 0)
@ -83,5 +84,13 @@ std::unique_ptr<Image<unsigned char> > FreeTypeFontEngine::loadGlyph(unsigned ch
} }
} }
image->setData(data); image->setData(data);
return image;
auto glyph = std::make_unique<FontGlyph>(mWorkingFontFace->glyph->bitmap.width,
mWorkingFontFace->glyph->bitmap.rows,
mWorkingFontFace->glyph->bitmap_left,
mWorkingFontFace->glyph->bitmap_top,
mWorkingFontFace->glyph->advance.x,
std::move(image));
return glyph;
} }

View file

@ -19,7 +19,7 @@ public:
void loadFontFace(const std::filesystem::path& fontFile, int penSize = 16) override; void loadFontFace(const std::filesystem::path& fontFile, int penSize = 16) override;
std::unique_ptr<Image<unsigned char> > loadGlyph(unsigned charCode) override; std::unique_ptr<FontGlyph> loadGlyph(unsigned charCode) override;
private: private:
std::filesystem::path mSystemFontLocation{"/usr/share/fonts/"}; std::filesystem::path mSystemFontLocation{"/usr/share/fonts/"};

View file

@ -3,8 +3,7 @@
#include <memory> #include <memory>
#include <filesystem> #include <filesystem>
template<typename T> class FontGlyph;
class Image;
class IFontEngine class IFontEngine
{ {
@ -16,5 +15,5 @@ public:
virtual void loadFontFace(const std::filesystem::path& fontFile, int penSize = 16) = 0; virtual void loadFontFace(const std::filesystem::path& fontFile, int penSize = 16) = 0;
virtual std::unique_ptr<Image<unsigned char> > loadGlyph(unsigned charCode) = 0; virtual std::unique_ptr<FontGlyph> loadGlyph(unsigned charCode) = 0;
}; };

View file

@ -1,9 +1,8 @@
#pragma once #pragma once
#include "IFont.h"
#include <iostream> #include <iostream>
#include <stdint.h> #include <stdint.h>
#include "IFont.h"
class TrueTypeFont : public IFont class TrueTypeFont : public IFont
{ {

View file

@ -19,8 +19,14 @@ set(OpenGL_GL_PREFERENCE "GLVND")
find_package(OpenGL QUIET) find_package(OpenGL QUIET)
if (OpenGL_FOUND) if (OpenGL_FOUND)
list(APPEND platform_LIBS OpenGL::GL OpenGL::GLU) list(APPEND platform_LIBS OpenGL::GL OpenGL::GLU)
list(APPEND graphics_LIB_INCLUDES opengl/OpenGlPainter.cpp) list(APPEND graphics_LIB_INCLUDES
list(APPEND graphics_HEADERS opengl/OpenGlPainter.h) opengl/OpenGlPainter.cpp
opengl/OpenGlFontTexture.cpp
opengl/OpenGlShaderProgram.cpp)
list(APPEND graphics_HEADERS
opengl/OpenGlPainter.h
opengl/OpenGlFontTexture.h
opengl/OpenGlShaderProgram.h)
else() else()
message(STATUS "OpenGL headers not found - skipping OpenGL support") message(STATUS "OpenGL headers not found - skipping OpenGL support")
endif() endif()

View file

@ -2,6 +2,8 @@
#include "AbstractPainter.h" #include "AbstractPainter.h"
#include "OpenGlPainter.h" #include "OpenGlPainter.h"
#include "OpenGlShaderProgram.h"
#include "OpenGlFontTexture.h"
#include "RasterPainter.h" #include "RasterPainter.h"
#include "Grid.h" #include "Grid.h"
#include "TriMesh.h" #include "TriMesh.h"
@ -40,6 +42,11 @@ DrawingSurface* DrawingContext::getSurface() const
return mSurface; return mSurface;
} }
FontsManager* DrawingContext::getFontsManager() const
{
return mFontsManager;
}
void DrawingContext::paint() void DrawingContext::paint()
{ {
mScene->update(mFontsManager, mDrawingMode == DrawingMode::RASTER ? mSurface->getImage() : nullptr); mScene->update(mFontsManager, mDrawingMode == DrawingMode::RASTER ? mSurface->getImage() : nullptr);

View file

@ -25,6 +25,8 @@ public:
DrawingSurface* getSurface() const; DrawingSurface* getSurface() const;
FontsManager* getFontsManager() const;
void paint(); void paint();
private: private:

View file

@ -0,0 +1,36 @@
#include "OpenGlFontTexture.h"
#include "FontGlyph.h"
#include "Image.h"
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
OpenGlFontTexture::OpenGlFontTexture(FontGlyph* glyph)
: mGlyph(glyph)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_2D, mHandle);
auto buffer = glyph->getImage()->getDataPtr();
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
mGlyph->getWidth(),
mGlyph->getHeight(),
0,
GL_RED,
GL_UNSIGNED_BYTE,
buffer
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

View file

@ -0,0 +1,13 @@
#pragma once
class FontGlyph;
class OpenGlFontTexture
{
public:
OpenGlFontTexture(FontGlyph* glyph);
private:
unsigned int mHandle{0};
FontGlyph* mGlyph{nullptr};
};

View file

@ -5,6 +5,15 @@
#include "Scene.h" #include "Scene.h"
#include "TriMesh.h" #include "TriMesh.h"
#include "FontsManager.h"
#include "FontGlyph.h"
#include "OpenGlFontTexture.h"
#include "OpenGlShaderProgram.h"
#include "TextData.h"
#include "File.h"
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#endif #endif
@ -14,30 +23,18 @@
#include <GL/glu.h> #include <GL/glu.h>
#include <GL/glx.h> #include <GL/glx.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream> #include <iostream>
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n";
OpenGlPainter::OpenGlPainter() OpenGlPainter::OpenGlPainter()
{ {
} }
void OpenGlPainter::initialize() void OpenGlPainter::initializeMeshShader()
{ {
if (auto context = glXGetCurrentContext()) if (auto context = glXGetCurrentContext())
{ {
@ -54,99 +51,70 @@ void OpenGlPainter::initialize()
glGetIntegerv(GL_MINOR_VERSION, &minor_version); glGetIntegerv(GL_MINOR_VERSION, &minor_version);
std::cout << "Using opengl version " << major_version << "|" << minor_version << std::endl; std::cout << "Using opengl version " << major_version << "|" << minor_version << std::endl;
std::cout << "Creating opengl painter" << std::endl; auto vert_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/default.vert";
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); auto frag_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/default.frag";
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
int success; mMeshShaderProgram = std::make_unique<OpenGlShaderProgram>(vert_shader_path, frag_shader_path);
char infoLog[512]; }
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success) void OpenGlPainter::initializeTextShader()
{
auto vert_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/text.vert";
auto frag_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/text.frag";
mTextShaderProgram = std::make_unique<OpenGlShaderProgram>(vert_shader_path, frag_shader_path);
}
void OpenGlPainter::renderTextLayer(const TextData& textData, DrawingContext* context)
{
if (!mTextShaderProgram)
{ {
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog); initializeTextShader();
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED: " << std::string(infoLog) << std::endl; }
if (auto errCode = glGetError(); errCode != GL_NO_ERROR) auto first_char = textData.mContent[0];
{ auto iter = mFontTextures.find(first_char);
auto errString = gluErrorString(errCode); OpenGlFontTexture* working_texture{nullptr};
std::cout << "Got gl error" << errString << std::endl; if (iter == mFontTextures.end())
} {
auto glyph = context->getFontsManager()->getGlyph(first_char);
auto new_texture = std::make_unique<OpenGlFontTexture>(nullptr);
working_texture = new_texture.get();
mFontTextures[first_char] = std::move(new_texture);
} }
else else
{ {
std::cout << "Shader compiled ok" << std::endl; working_texture = iter->second.get();
if (auto errCode = glGetError(); errCode != GL_NO_ERROR)
{
auto errString = gluErrorString(errCode);
std::cout << "Got gl error after ok" << errString << std::endl;
}
} }
unsigned int fragmentShader; glEnable(GL_BLEND);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED: " << infoLog << std::endl;
}
mShaderProgram = glCreateProgram();
glAttachShader(mShaderProgram, vertexShader);
glAttachShader(mShaderProgram, fragmentShader);
glLinkProgram(mShaderProgram);
glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(mShaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
mInitialized = true;
} }
void OpenGlPainter::paint(DrawingContext* context) void OpenGlPainter::renderMeshLayer(TriMesh* mesh, DrawingContext* context)
{ {
if (!mInitialized) if (!mMeshShaderProgram)
{ {
initialize(); initializeMeshShader();
} }
auto surface = context->getSurface();
const auto width = double(surface->getWidth());
const auto height = double(surface->getHeight());
const auto num_mesh = context->getScene()->getNumMeshes();
glViewport(0, 0, width, height);
//glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
//glScissor(0, 0, width, height);
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
glClearColor(0.5, 0.5, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
float vertices[] = { float vertices[] = {
-0.5f, -0.5f, 0.0f, 0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, // bottom right
0.0f, 0.5f, 0.0f -0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
}; };
unsigned int vbo{0}; unsigned int vbo{0};
glGenBuffers(1, &vbo); glGenBuffers(1, &vbo);
unsigned int EBO;
glGenBuffers(1, &EBO);
unsigned int VAO; unsigned int VAO;
glGenVertexArrays(1, &VAO); glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO); glBindVertexArray(VAO);
@ -154,14 +122,22 @@ void OpenGlPainter::paint(DrawingContext* context)
glBindBuffer(GL_ARRAY_BUFFER, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glUseProgram(mShaderProgram); int vertexColorLocation = glGetUniformLocation(mMeshShaderProgram->getHandle(), "ourColor");
glUseProgram(mMeshShaderProgram->getHandle());
glBindVertexArray(VAO); glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3); glUniform4f(vertexColorLocation, 0.0f, 1.0, 0.0f, 1.0f);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
/* /*
std::cout << "Bounds are : " << width << " | " << height << std::endl; std::cout << "Bounds are : " << width << " | " << height << std::endl;
@ -207,6 +183,31 @@ void OpenGlPainter::paint(DrawingContext* context)
break; break;
} }
*/ */
}
void OpenGlPainter::paint(DrawingContext* context)
{
auto surface = context->getSurface();
const auto width = double(surface->getWidth());
const auto height = double(surface->getHeight());
glViewport(0, 0, width, height);
//glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
//glScissor(0, 0, width, height);
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
glClearColor(0.5, 0.5, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
const auto num_mesh = context->getScene()->getNumMeshes();
//renderMeshLayer(nullptr, context);
auto text_data = context->getScene()->getTextData();
renderTextLayer(text_data[0], context);
glFlush(); glFlush();
} }

View file

@ -2,21 +2,33 @@
#include "AbstractPainter.h" #include "AbstractPainter.h"
#include <unordered_map>
#include <memory>
class DrawingContext; class DrawingContext;
class OpenGlFontTexture;
class OpenGlShaderProgram;
class TextData;
class TriMesh;
class OpenGlPainter : public AbstractPainter class OpenGlPainter : public AbstractPainter
{ {
public: public:
OpenGlPainter(); OpenGlPainter();
void initialize();
void paint(DrawingContext* context) override; void paint(DrawingContext* context) override;
private: private:
bool mInitialized{false}; void initializeMeshShader();
unsigned int mShaderProgram{0}; void initializeTextShader();
void renderTextLayer(const TextData& textData, DrawingContext* context);
void renderMeshLayer(TriMesh* mesh, DrawingContext* context);
std::unique_ptr<OpenGlShaderProgram> mMeshShaderProgram;
std::unique_ptr<OpenGlShaderProgram> mTextShaderProgram;
std::unordered_map<char, std::unique_ptr<OpenGlFontTexture> > mFontTextures;
}; };

View file

@ -0,0 +1,68 @@
#include "OpenGlShaderProgram.h"
#include "File.h"
#include "FileLogger.h"
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glu.h>
OpenGlShaderProgram::OpenGlShaderProgram(const Path& vertShaderPath, const Path& fragShaderPath)
{
const auto vert_shader_source = File(vertShaderPath).read();
const auto frag_shader_source = File(fragShaderPath).read();
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
const char* vert_source = vert_shader_source.c_str();
glShaderSource(vertexShader, 1, &vert_source, nullptr);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
MLOG_ERROR("ERROR::SHADER::VERTEX::COMPILATION_FAILED: " << infoLog);
if (auto errCode = glGetError(); errCode != GL_NO_ERROR)
{
auto errString = gluErrorString(errCode);
MLOG_ERROR("Got gl error " << errString);
}
}
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const char* frag_source = frag_shader_source.c_str();
glShaderSource(fragmentShader, 1, &frag_source, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
MLOG_ERROR("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED: " << infoLog);
}
mHandle = glCreateProgram();
glAttachShader(mHandle, vertexShader);
glAttachShader(mHandle, fragmentShader);
glLinkProgram(mHandle);
glGetProgramiv(mHandle, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(mHandle, 512, NULL, infoLog);
MLOG_ERROR("Shader linking FAILED: " << infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
unsigned int OpenGlShaderProgram::getHandle() const
{
return mHandle;
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <filesystem>
using Path = std::filesystem::path;
class OpenGlShaderProgram
{
public:
OpenGlShaderProgram(const Path& vertShaderPath, const Path& fragShaderPath);
unsigned int getHandle() const;
private:
unsigned int mHandle{0};
};

View file

@ -0,0 +1,11 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor; // the input variable from the vertex shader (same name and same type)
uniform vec4 ourColor; // we set this variable in the OpenGL code.
void main()
{
FragColor = ourColor;
}

View file

@ -0,0 +1,10 @@
#version 330 core
layout (location = 0) in vec3 aPos; // the position variable has attribute position 0
out vec4 vertexColor; // specify a color output to the fragment shader
void main()
{
gl_Position = vec4(aPos, 1.0); // see how we directly give a vec3 to vec4's constructor
vertexColor = vec4(aPos.x, aPos.y, 0.0, 1.0); // set the output variable to a dark-red color
}

View file

@ -0,0 +1,12 @@
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D text;
uniform vec3 textColor;
void main()
{
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
color = vec4(textColor, 1.0) * sampled;
}

View file

@ -0,0 +1,11 @@
#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
out vec2 TexCoords;
uniform mat4 projection;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
TexCoords = vertex.zw;
}

View file

@ -34,25 +34,28 @@ void Scene::update(FontsManager* fontsManager, Image<unsigned char>* image)
node->update(fontsManager); node->update(fontsManager);
layer->setIsDirty(false); layer->setIsDirty(false);
} }
mWorkingMeshs.push_back(dynamic_cast<TriMesh*>(node->getMesh())); mWorkingMeshs.push_back(dynamic_cast<TriMesh*>(node->getMesh()));
mTextures.push_back(nullptr); mTextures.push_back(nullptr);
} }
else else
{ {
auto node = layer->getTextNode(); auto node = dynamic_cast<TextNode*>(layer->getTextNode());
if (layer->getIsDirty()) if (layer->getIsDirty())
{ {
node->update(fontsManager); node->update(fontsManager);
layer->setIsDirty(false); layer->setIsDirty(false);
} }
mWorkingMeshs.push_back(dynamic_cast<TriMesh*>(node->getMesh())); mTextData.push_back(node->getTextData());
mTextures.push_back(node->getTexture());
} }
} }
} }
} }
const std::vector<TextData>& Scene::getTextData() const
{
return mTextData;
}
void Scene::processRectangleNode(RectangleNode* node) void Scene::processRectangleNode(RectangleNode* node)
{ {

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "TextData.h"
#include <vector> #include <vector>
#include <memory> #include <memory>
@ -15,6 +17,7 @@ class Image;
class Scene class Scene
{ {
public: public:
Scene() = default; Scene() = default;
void syncLayers(const std::vector<VisualLayer*>& layers); void syncLayers(const std::vector<VisualLayer*>& layers);
@ -27,11 +30,14 @@ public:
Image<unsigned char>* getTexture(std::size_t idx) const; Image<unsigned char>* getTexture(std::size_t idx) const;
private: const std::vector<TextData>& getTextData() const;
private:
void processRectangleNode(RectangleNode* node); void processRectangleNode(RectangleNode* node);
std::vector<TriMesh*> mWorkingMeshs;
std::vector<VisualLayer*> mLayers; std::vector<VisualLayer*> mLayers;
std::vector<TriMesh*> mWorkingMeshs;
std::vector<Image<unsigned char>* > mTextures; std::vector<Image<unsigned char>* > mTextures;
std::vector<TextData> mTextData;
}; };

View file

@ -0,0 +1,16 @@
#pragma once
#include "DiscretePoint.h"
#include "Color.h"
#include "FontItem.h"
class TextData
{
public:
TextData() = default;
DiscretePoint mLocation;
std::string mContent;
Color mFillColor;
Color mStrokeColor;
FontItem mFont;
};

View file

@ -4,17 +4,18 @@
#include "FontsManager.h" #include "FontsManager.h"
#include "IFontEngine.h" #include "IFontEngine.h"
#include "MeshPrimitives.h" #include "MeshPrimitives.h"
#include "FontItem.h"
#include "Color.h" #include "Color.h"
TextNode::TextNode(const std::string& content, const DiscretePoint& loc) TextNode::TextNode(const std::string& content, const DiscretePoint& loc)
: AbstractVisualNode(loc), : AbstractVisualNode(loc)
mContent(content),
mFontLabel("fixed"),
mFillColor(Color(255, 255, 255)),
mStrokeColor(Color(0, 0, 0))
{ {
// https://en.wikipedia.org/wiki/Fixed_(typeface)#:~:text=misc%2Dfixed%20is%20a%20collection,to%20a%20single%20font%20family. mTextData.mContent = content;
mTextData.mFont = FontItem("Arial", 16);
mTextData.mLocation = loc;
mTextData.mFillColor = Color(255, 255, 255);
mTextData.mStrokeColor = Color(0, 0, 0);
} }
TextNode::~TextNode() TextNode::~TextNode()
@ -29,36 +30,36 @@ std::unique_ptr<TextNode> TextNode::Create(const std::string& content, const Dis
const Color& TextNode::getFillColor() const const Color& TextNode::getFillColor() const
{ {
return mFillColor; return mTextData.mFillColor;
} }
const Color& TextNode::getStrokeColor() const const Color& TextNode::getStrokeColor() const
{ {
return mStrokeColor; return mTextData.mStrokeColor;
} }
std::string TextNode::getFontLabel() const std::string TextNode::getFontLabel() const
{ {
return mFontLabel; return {};
} }
std::string TextNode::getContent() const std::string TextNode::getContent() const
{ {
return mContent; return mTextData.mContent;
} }
void TextNode::setContent(const std::string& content) void TextNode::setContent(const std::string& content)
{ {
mContent = content; mTextData.mContent = content;
} }
void TextNode::setFillColor(const Color& color) void TextNode::setFillColor(const Color& color)
{ {
mFillColor = color; mTextData.mFillColor = color;
} }
void TextNode::setStrokeColor(const Color& color) void TextNode::setStrokeColor(const Color& color)
{ {
mStrokeColor = color; mTextData.mStrokeColor = color;
} }
void TextNode::update(FontsManager* drawingManager) void TextNode::update(FontsManager* drawingManager)
@ -67,32 +68,17 @@ void TextNode::update(FontsManager* drawingManager)
updateTexture(drawingManager); updateTexture(drawingManager);
} }
const TextData& TextNode::getTextData() const
{
return mTextData;
}
void TextNode::updateMesh() void TextNode::updateMesh()
{ {
double font_height = 16;
double font_width = 16;
double text_width = mContent.size() * font_width;
const auto rect = Rectangle(mLocation, text_width, font_height);
auto mesh = MeshPrimitives::build(rect);
auto color = Color(0, 0, 0, 1.0);
mesh->addConstantFaceVectorAttribute("Color", color.getAsVectorDouble());
mMesh = std::move(mesh);
} }
void TextNode::updateTexture(FontsManager* fontsManager) void TextNode::updateTexture(FontsManager* fontsManager)
{ {
fontsManager->getFontEngine()->loadFontFace("truetype/msttcorefonts/arial.ttf");
auto glyph = fontsManager->getFontEngine()->loadGlyph('A');
if (!glyph)
{
return;
}
mTexture = std::make_unique<Image<unsigned char> >(glyph->getWidth(), glyph->getHeight());
mTexture->setData(glyph->getData());
} }

View file

@ -4,12 +4,12 @@
#include "AbstractVisualNode.h" #include "AbstractVisualNode.h"
#include "Color.h" #include "Color.h"
#include "FontItem.h"
#include "TextData.h"
#include <memory> #include <memory>
#include <string> #include <string>
class Color;
class TextNode : public AbstractVisualNode class TextNode : public AbstractVisualNode
{ {
public: public:
@ -24,6 +24,9 @@ public:
std::string getContent() const; std::string getContent() const;
std::string getFontLabel() const; std::string getFontLabel() const;
const TextData& getTextData() const;
void setContent(const std::string& content); void setContent(const std::string& content);
void setFillColor(const Color& color); void setFillColor(const Color& color);
void setStrokeColor(const Color& color); void setStrokeColor(const Color& color);
@ -34,10 +37,7 @@ private:
void updateMesh() override; void updateMesh() override;
void updateTexture(FontsManager* fontsManager) override; void updateTexture(FontsManager* fontsManager) override;
std::string mContent; TextData mTextData;
std::string mFontLabel;
Color mFillColor;
Color mStrokeColor;
}; };
using TextNodetr = std::unique_ptr<TextNode>; using TextNodetr = std::unique_ptr<TextNode>;

View file

@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include "IFontEngine.h" #include "IFontEngine.h"
#include "FontsManager.h" #include "FontsManager.h"
#include "FontGlyph.h"
namespace mt namespace mt
{ {

View file

@ -1,5 +1,6 @@
#include "FreeTypeFontEngine.h" #include "FreeTypeFontEngine.h"
#include "FontGlyph.h"
#include "Image.h" #include "Image.h"
#include <iostream> #include <iostream>