Text rendering working ok.

This commit is contained in:
James Grogan 2022-11-15 17:16:38 +00:00
parent eef93efc29
commit 4849d83fcf
10 changed files with 127 additions and 42 deletions

View file

@ -5,9 +5,9 @@ FontGlyph::FontGlyph(unsigned width, unsigned height, unsigned bearingX, unsigne
: mImage(std::move(image)), : mImage(std::move(image)),
mWidth(width), mWidth(width),
mHeight(height), mHeight(height),
mBearingX(mBearingX), mBearingX(bearingX),
mBearingY(mBearingY), mBearingY(bearingY),
mAdvanceX(mAdvanceX) mAdvanceX(advanceX)
{ {
} }

View file

@ -28,6 +28,16 @@ public:
mPath = path; mPath = path;
} }
const std::string& getFaceName() const
{
return mFaceName;
}
unsigned getSize() const
{
return mSize;
}
private: private:
unsigned mSize{16}; unsigned mSize{16};
std::string mFaceName; std::string mFaceName;

View file

@ -20,8 +20,12 @@ IFontEngine* FontsManager::getFontEngine() const
return mFontEngine.get(); 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); auto iter = mGlyphs.find(c);
if(iter != mGlyphs.end()) if(iter != mGlyphs.end())
{ {

View file

@ -15,7 +15,7 @@ public:
IFontEngine* getFontEngine() const; IFontEngine* getFontEngine() const;
FontGlyph* getGlyph(char c); FontGlyph* getGlyph(const std::string& fontFace, int size, char c);
private: private:
std::unique_ptr<IFontEngine> mFontEngine; std::unique_ptr<IFontEngine> mFontEngine;

View file

@ -25,6 +25,11 @@ void FreeTypeFontEngine::loadFontFace(const std::filesystem::path& fontFile, int
initialize(); initialize();
} }
if (mWorkingFontFace)
{
return;
}
const auto full_path = mSystemFontLocation / fontFile; const auto full_path = mSystemFontLocation / fontFile;
const auto error = FT_New_Face(mLibrary, full_path.c_str(), 0, &mWorkingFontFace ); const auto error = FT_New_Face(mLibrary, full_path.c_str(), 0, &mWorkingFontFace );
if ( error == FT_Err_Unknown_File_Format ) if ( error == FT_Err_Unknown_File_Format )
@ -40,7 +45,7 @@ void FreeTypeFontEngine::loadFontFace(const std::filesystem::path& fontFile, int
std::unique_ptr<FontGlyph> 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, charCode );
if (glyph_index == 0) if (glyph_index == 0)
{ {
MLOG_ERROR("Got the null glyph"); MLOG_ERROR("Got the null glyph");

View file

@ -34,3 +34,8 @@ OpenGlFontTexture::OpenGlFontTexture(FontGlyph* glyph)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} }
FontGlyph* OpenGlFontTexture::getGlyph() const
{
return mGlyph;
}

View file

@ -7,6 +7,13 @@ class OpenGlFontTexture
public: public:
OpenGlFontTexture(FontGlyph* glyph); OpenGlFontTexture(FontGlyph* glyph);
unsigned int getHandle() const
{
return mHandle;
}
FontGlyph* getGlyph() const;
private: private:
unsigned int mHandle{0}; unsigned int mHandle{0};
FontGlyph* mGlyph{nullptr}; FontGlyph* mGlyph{nullptr};

View file

@ -72,23 +72,80 @@ void OpenGlPainter::renderTextLayer(const TextData& textData, DrawingContext* co
initializeTextShader(); initializeTextShader();
} }
auto first_char = textData.mContent[0]; for (auto c : textData.mContent)
auto iter = mFontTextures.find(first_char);
OpenGlFontTexture* working_texture{nullptr};
if (iter == mFontTextures.end())
{ {
auto glyph = context->getFontsManager()->getGlyph(first_char); if (auto iter = mFontTextures.find(c); iter == mFontTextures.end())
auto new_texture = std::make_unique<OpenGlFontTexture>(nullptr); {
working_texture = new_texture.get(); auto glyph = context->getFontsManager()->getGlyph(textData.mFont.getFaceName(), textData.mFont.getSize(), c);
mFontTextures[first_char] = std::move(new_texture); auto new_texture = std::make_unique<OpenGlFontTexture>(glyph);
mFontTextures[c] = std::move(new_texture);
} }
else
{
working_texture = iter->second.get();
} }
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 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) void OpenGlPainter::renderMeshLayer(TriMesh* mesh, DrawingContext* context)
@ -193,6 +250,8 @@ void OpenGlPainter::paint(DrawingContext* context)
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
//glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); //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); //glScissor(0, 0, width, height);
//glMatrixMode(GL_PROJECTION); //glMatrixMode(GL_PROJECTION);
//glLoadIdentity(); //glLoadIdentity();

View file

@ -145,8 +145,7 @@ uint32_t XcbInterface::getEventMask()
return XCB_EVENT_MASK_KEY_RELEASE | return XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
XCB_EVENT_MASK_RESIZE_REDIRECT;
} }
void XcbInterface::addWindow(mt::Window* window) void XcbInterface::addWindow(mt::Window* window)
@ -211,42 +210,39 @@ void XcbInterface::loop()
mDesktopManager->onUiEvent(std::move(ui_event)); mDesktopManager->onUiEvent(std::move(ui_event));
break; break;
} }
case XCB_RESIZE_REQUEST: case XCB_CONFIGURE_NOTIFY:
{ {
auto resize = (xcb_resize_request_event_t*) event; auto config_event = (xcb_configure_notify_event_t*) event;
int width = 1; auto mainWindow = mDesktopManager->getWindowManager()->getMainWindow();
int height = 1; auto width = mainWindow->getWidth();
if (resize->width > 0) 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<ResizeEvent>(width, height); auto ui_event = std::make_unique<ResizeEvent>(width, height);
mDesktopManager->onUiEvent(std::move(ui_event)); mDesktopManager->onUiEvent(std::move(ui_event));
}
break; break;
} }
default: default:
/* Unknown event type, ignore it */ /* Unknown event type, ignore it */
break; break;
} }
onEventsDispatched();
free(event); free(event);
} }
} }
void XcbInterface::onEventsDispatched()
{
if (mDesktopManager->isModified())
{
mDesktopManager->setIsModified(false);
auto mainWindow = mDesktopManager->getWindowManager()->getMainWindow();
mainWindow->clear();
}
}
void XcbInterface::shutDown() void XcbInterface::shutDown()
{ {
mDesktopManager->getWindowManager()->clearPlatformWindows(); mDesktopManager->getWindowManager()->clearPlatformWindows();

View file

@ -38,7 +38,6 @@ public:
private: private:
void initialize() override; void initialize() override;
void onPaint(); void onPaint();
void onEventsDispatched();
void onExposeEvent(xcb_expose_event_t* event); void onExposeEvent(xcb_expose_event_t* event);
void initializeHardwareRendering() override; void initializeHardwareRendering() override;