Text rendering working ok.
This commit is contained in:
parent
eef93efc29
commit
4849d83fcf
10 changed files with 127 additions and 42 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
mDesktopManager->onUiEvent(std::move(ui_event));
|
||||||
}
|
}
|
||||||
auto ui_event = std::make_unique<ResizeEvent>(width, height);
|
|
||||||
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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue