From 4849d83fcfb4bf0a46de430bdfca25d8ed3b10e0 Mon Sep 17 00:00:00 2001 From: James Grogan Date: Tue, 15 Nov 2022 17:16:38 +0000 Subject: [PATCH] Text rendering working ok. --- src/fonts/FontGlyph.cpp | 6 +- src/fonts/FontItem.h | 10 +++ src/fonts/FontsManager.cpp | 6 +- src/fonts/FontsManager.h | 2 +- src/fonts/FreeTypeFontEngine.cpp | 7 +- src/graphics/opengl/OpenGlFontTexture.cpp | 5 ++ src/graphics/opengl/OpenGlFontTexture.h | 7 ++ src/graphics/opengl/OpenGlPainter.cpp | 83 ++++++++++++++++--- .../ui_interfaces/x11/XcbInterface.cpp | 42 +++++----- src/windows/ui_interfaces/x11/XcbInterface.h | 1 - 10 files changed, 127 insertions(+), 42 deletions(-) diff --git a/src/fonts/FontGlyph.cpp b/src/fonts/FontGlyph.cpp index 0a2c24f..faa251c 100644 --- a/src/fonts/FontGlyph.cpp +++ b/src/fonts/FontGlyph.cpp @@ -5,9 +5,9 @@ FontGlyph::FontGlyph(unsigned width, unsigned height, unsigned bearingX, unsigne : mImage(std::move(image)), mWidth(width), mHeight(height), - mBearingX(mBearingX), - mBearingY(mBearingY), - mAdvanceX(mAdvanceX) + mBearingX(bearingX), + mBearingY(bearingY), + mAdvanceX(advanceX) { } diff --git a/src/fonts/FontItem.h b/src/fonts/FontItem.h index 5b48bf9..25da69e 100644 --- a/src/fonts/FontItem.h +++ b/src/fonts/FontItem.h @@ -28,6 +28,16 @@ public: mPath = path; } + const std::string& getFaceName() const + { + return mFaceName; + } + + unsigned getSize() const + { + return mSize; + } + private: unsigned mSize{16}; std::string mFaceName; diff --git a/src/fonts/FontsManager.cpp b/src/fonts/FontsManager.cpp index 4d00e7f..91c2e9e 100644 --- a/src/fonts/FontsManager.cpp +++ b/src/fonts/FontsManager.cpp @@ -20,8 +20,12 @@ IFontEngine* FontsManager::getFontEngine() const return mFontEngine.get(); } -FontGlyph* FontsManager::getGlyph(char c) +FontGlyph* FontsManager::getGlyph(const std::string& fontFace, int size, char c) { + auto path = std::filesystem::path("truetype/msttcorefonts/arial.ttf"); + + mFontEngine->loadFontFace(path, size); + auto iter = mGlyphs.find(c); if(iter != mGlyphs.end()) { diff --git a/src/fonts/FontsManager.h b/src/fonts/FontsManager.h index 19fe3bd..105c461 100644 --- a/src/fonts/FontsManager.h +++ b/src/fonts/FontsManager.h @@ -15,7 +15,7 @@ public: IFontEngine* getFontEngine() const; - FontGlyph* getGlyph(char c); + FontGlyph* getGlyph(const std::string& fontFace, int size, char c); private: std::unique_ptr mFontEngine; diff --git a/src/fonts/FreeTypeFontEngine.cpp b/src/fonts/FreeTypeFontEngine.cpp index bf26e3e..5caf414 100644 --- a/src/fonts/FreeTypeFontEngine.cpp +++ b/src/fonts/FreeTypeFontEngine.cpp @@ -25,6 +25,11 @@ void FreeTypeFontEngine::loadFontFace(const std::filesystem::path& fontFile, int initialize(); } + if (mWorkingFontFace) + { + return; + } + const auto full_path = mSystemFontLocation / fontFile; const auto error = FT_New_Face(mLibrary, full_path.c_str(), 0, &mWorkingFontFace ); if ( error == FT_Err_Unknown_File_Format ) @@ -40,7 +45,7 @@ void FreeTypeFontEngine::loadFontFace(const std::filesystem::path& fontFile, int std::unique_ptr FreeTypeFontEngine::loadGlyph(unsigned charCode) { - auto glyph_index = FT_Get_Char_Index( mWorkingFontFace, 65 ); + auto glyph_index = FT_Get_Char_Index( mWorkingFontFace, charCode ); if (glyph_index == 0) { MLOG_ERROR("Got the null glyph"); diff --git a/src/graphics/opengl/OpenGlFontTexture.cpp b/src/graphics/opengl/OpenGlFontTexture.cpp index 048b670..8ae5134 100644 --- a/src/graphics/opengl/OpenGlFontTexture.cpp +++ b/src/graphics/opengl/OpenGlFontTexture.cpp @@ -34,3 +34,8 @@ OpenGlFontTexture::OpenGlFontTexture(FontGlyph* glyph) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } + +FontGlyph* OpenGlFontTexture::getGlyph() const +{ + return mGlyph; +} diff --git a/src/graphics/opengl/OpenGlFontTexture.h b/src/graphics/opengl/OpenGlFontTexture.h index 9388bc9..fcfc96a 100644 --- a/src/graphics/opengl/OpenGlFontTexture.h +++ b/src/graphics/opengl/OpenGlFontTexture.h @@ -7,6 +7,13 @@ class OpenGlFontTexture public: OpenGlFontTexture(FontGlyph* glyph); + unsigned int getHandle() const + { + return mHandle; + } + + FontGlyph* getGlyph() const; + private: unsigned int mHandle{0}; FontGlyph* mGlyph{nullptr}; diff --git a/src/graphics/opengl/OpenGlPainter.cpp b/src/graphics/opengl/OpenGlPainter.cpp index 9fa1177..bc13bb1 100644 --- a/src/graphics/opengl/OpenGlPainter.cpp +++ b/src/graphics/opengl/OpenGlPainter.cpp @@ -72,23 +72,80 @@ void OpenGlPainter::renderTextLayer(const TextData& textData, DrawingContext* co initializeTextShader(); } - auto first_char = textData.mContent[0]; - auto iter = mFontTextures.find(first_char); - OpenGlFontTexture* working_texture{nullptr}; - if (iter == mFontTextures.end()) + for (auto c : textData.mContent) { - auto glyph = context->getFontsManager()->getGlyph(first_char); - auto new_texture = std::make_unique(nullptr); - working_texture = new_texture.get(); - mFontTextures[first_char] = std::move(new_texture); - } - else - { - working_texture = iter->second.get(); + if (auto iter = mFontTextures.find(c); iter == mFontTextures.end()) + { + auto glyph = context->getFontsManager()->getGlyph(textData.mFont.getFaceName(), textData.mFont.getSize(), c); + auto new_texture = std::make_unique(glyph); + mFontTextures[c] = std::move(new_texture); + } } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + const auto width = float(context->getSurface()->getWidth()); + const auto height = float(context->getSurface()->getHeight()); + + glm::mat4 projection = glm::ortho(0.0f, width, 0.0f, height); + + unsigned int VAO, VBO; + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + glUseProgram(mTextShaderProgram->getHandle()); + glUniform3f(glGetUniformLocation(mTextShaderProgram->getHandle(), "textColor"), 0.0, 0.0, 0.0); + glUniformMatrix4fv(glGetUniformLocation(mTextShaderProgram->getHandle(), "projection"), 1, GL_FALSE, glm::value_ptr(projection)); + glActiveTexture(GL_TEXTURE0); + glBindVertexArray(VAO); + + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + // iterate through all characters + float x = textData.mLocation.GetX(); + const float y = textData.mLocation.GetY(); + + for (auto c : textData.mContent) + { + auto texture = mFontTextures[c].get(); + + float xpos = x + texture->getGlyph()->getBearingX(); + float ypos = y - (texture->getGlyph()->getHeight() - texture->getGlyph()->getBearingY()); + + float w = texture->getGlyph()->getWidth(); + float h = texture->getGlyph()->getHeight(); + // update VBO for each character + 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 over quad + glBindTexture(GL_TEXTURE_2D, texture->getHandle()); + // update content of VBO memory + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + glBindBuffer(GL_ARRAY_BUFFER, 0); + // render quad + glDrawArrays(GL_TRIANGLES, 0, 6); + // now advance cursors for next glyph (note that advance is number of 1/64 pixels) + x += (texture->getGlyph()->getAdvanceX() >> 6); // bitshift by 6 to get value in pixels (2^6 = 64) + } + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); } void OpenGlPainter::renderMeshLayer(TriMesh* mesh, DrawingContext* context) @@ -193,6 +250,8 @@ void OpenGlPainter::paint(DrawingContext* context) glViewport(0, 0, width, height); //glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + glOrtho(0, width, 0, height, -1.0, 1.0); + //glScissor(0, 0, width, height); //glMatrixMode(GL_PROJECTION); //glLoadIdentity(); diff --git a/src/windows/ui_interfaces/x11/XcbInterface.cpp b/src/windows/ui_interfaces/x11/XcbInterface.cpp index 6926f01..2cc73ed 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.cpp +++ b/src/windows/ui_interfaces/x11/XcbInterface.cpp @@ -145,8 +145,7 @@ uint32_t XcbInterface::getEventMask() return XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | - XCB_EVENT_MASK_EXPOSURE | - XCB_EVENT_MASK_RESIZE_REDIRECT; + XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY; } void XcbInterface::addWindow(mt::Window* window) @@ -211,42 +210,39 @@ void XcbInterface::loop() mDesktopManager->onUiEvent(std::move(ui_event)); break; } - case XCB_RESIZE_REQUEST: + case XCB_CONFIGURE_NOTIFY: { - auto resize = (xcb_resize_request_event_t*) event; - int width = 1; - int height = 1; - if (resize->width > 0) + auto config_event = (xcb_configure_notify_event_t*) event; + auto mainWindow = mDesktopManager->getWindowManager()->getMainWindow(); + auto width = mainWindow->getWidth(); + auto height = mainWindow->getHeight(); + + bool changed = false; + if (config_event->width != width) { - width = resize->width; + width = config_event->width; + changed = true; } - if (resize->height > 0) + if (config_event->height != height) { - height = resize->height; + height = config_event->height; + changed = true; + } + if (changed) + { + auto ui_event = std::make_unique(width, height); + mDesktopManager->onUiEvent(std::move(ui_event)); } - auto ui_event = std::make_unique(width, height); - mDesktopManager->onUiEvent(std::move(ui_event)); break; } default: /* Unknown event type, ignore it */ break; } - onEventsDispatched(); free(event); } } -void XcbInterface::onEventsDispatched() -{ - if (mDesktopManager->isModified()) - { - mDesktopManager->setIsModified(false); - auto mainWindow = mDesktopManager->getWindowManager()->getMainWindow(); - mainWindow->clear(); - } -} - void XcbInterface::shutDown() { mDesktopManager->getWindowManager()->clearPlatformWindows(); diff --git a/src/windows/ui_interfaces/x11/XcbInterface.h b/src/windows/ui_interfaces/x11/XcbInterface.h index 3431ea7..c6513d8 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.h +++ b/src/windows/ui_interfaces/x11/XcbInterface.h @@ -38,7 +38,6 @@ public: private: void initialize() override; void onPaint(); - void onEventsDispatched(); void onExposeEvent(xcb_expose_event_t* event); void initializeHardwareRendering() override;