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)),
mWidth(width),
mHeight(height),
mBearingX(mBearingX),
mBearingY(mBearingY),
mAdvanceX(mAdvanceX)
mBearingX(bearingX),
mBearingY(bearingY),
mAdvanceX(advanceX)
{
}

View file

@ -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;

View file

@ -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())
{

View file

@ -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<IFontEngine> mFontEngine;

View file

@ -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<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)
{
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);
}
FontGlyph* OpenGlFontTexture::getGlyph() const
{
return mGlyph;
}

View file

@ -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};

View file

@ -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<OpenGlFontTexture>(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<OpenGlFontTexture>(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();

View file

@ -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<ResizeEvent>(width, height);
mDesktopManager->onUiEvent(std::move(ui_event));
}
auto ui_event = std::make_unique<ResizeEvent>(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();

View file

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