diff --git a/src/graphics/opengl/Window.cpp b/src/graphics/opengl/Window.cpp index 662d7a7..4d86fe3 100644 --- a/src/graphics/opengl/Window.cpp +++ b/src/graphics/opengl/Window.cpp @@ -50,16 +50,16 @@ bool Window::initGLFW() { glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); Window *thiz = reinterpret_cast(glfwGetWindowUserPointer(window)); - const float sx = (float) width / thiz->windowWidth; - const float sy = (float) height / thiz->windowHeight; thiz->windowWidth = width; thiz->windowHeight = height; for (const std::unique_ptr &boxComponent : thiz->boxComponents) { boxComponent->resize(width, height); } + thiz->y = 950; for (const std::unique_ptr &component : thiz->components) { TextComponent *textComponent = dynamic_cast(component.get()); - textComponent->resize(sx, sy); + textComponent->resize(0, thiz->y, width, height); + thiz->y -= textComponent->height; } }); glfwMakeContextCurrent(window); @@ -155,12 +155,12 @@ void Window::render() { glfwSwapBuffers(window); } -void Window::setDOM(std::shared_ptr rootNode) { +void Window::setDOM(const std::shared_ptr rootNode) { domRootNode = rootNode; domDirty = true; } -void Window::drawNode(std::shared_ptr node) { +void Window::drawNode(const std::shared_ptr node) { if (node->nodeType == NodeType::TAG) { TagNode *tagNode = dynamic_cast(node.get()); std::unique_ptr component = tagNode->render(*tagNode, y, windowWidth, windowHeight); diff --git a/src/graphics/opengl/Window.h b/src/graphics/opengl/Window.h index 00ead5e..ec5c4e1 100644 --- a/src/graphics/opengl/Window.h +++ b/src/graphics/opengl/Window.h @@ -23,8 +23,9 @@ public: const GLuint compileShader(const GLenum shaderType, const char *shaderSource) const; const GLuint compileProgram(const GLuint vertexShader, const GLuint fragmentShader) const; void render(); - void setDOM(std::shared_ptr rootNode); - void drawNode(std::shared_ptr rootNode); + void setDOM(const std::shared_ptr rootNode); + void drawNode(const std::shared_ptr rootNode); + void repositionNode(const std::shared_ptr rootNode); GLFWwindow *window; int windowWidth; int windowHeight; diff --git a/src/graphics/opengl/components/TextComponent.cpp b/src/graphics/opengl/components/TextComponent.cpp index c2b09f9..900f9f0 100644 --- a/src/graphics/opengl/components/TextComponent.cpp +++ b/src/graphics/opengl/components/TextComponent.cpp @@ -1,50 +1,17 @@ #include "TextComponent.h" -#include "../../text/TextRasterizer.h" -#include TextComponent::TextComponent(const std::string &text, const int x, const int y, const int fontSize, const bool bold, const int windowWidth, const int windowHeight) { + this->text = text; this->x = x; this->y = y; + this->fontSize = fontSize; + this->bold = bold; - const std::unique_ptr textRasterizer = std::make_unique("DejaVuSerif.ttf", fontSize, 72, bold); - unsigned int glyphCount; - std::unique_ptr glyphs = textRasterizer->rasterize(text, x, y, height, glyphCount); - if (glyphs == nullptr) { - return; - } - for (int i = 0; i < glyphCount; i++) { - const Glyph &glyph = glyphs[i]; - - float vx0 = glyph.x0; - float vy0 = glyph.y0; - float vx1 = glyph.x1; - float vy1 = glyph.y1; - pointToViewport(vx0, vy0, windowWidth, windowHeight); - pointToViewport(vx1, vy1, windowWidth, windowHeight); - - std::unique_ptr vertices = std::make_unique(20); - vertices[(0 * 5) + 0] = vx0; - vertices[(0 * 5) + 1] = vy0; - vertices[(0 * 5) + 2] = 0.0f; - vertices[(0 * 5) + 3] = glyph.s0; - vertices[(0 * 5) + 4] = glyph.t0; - vertices[(1 * 5) + 0] = vx0; - vertices[(1 * 5) + 1] = vy1; - vertices[(1 * 5) + 2] = 0.0f; - vertices[(1 * 5) + 3] = glyph.s0; - vertices[(1 * 5) + 4] = glyph.t1; - vertices[(2 * 5) + 0] = vx1; - vertices[(2 * 5) + 1] = vy1; - vertices[(2 * 5) + 2] = 0.0f; - vertices[(2 * 5) + 3] = glyph.s1; - vertices[(2 * 5) + 4] = glyph.t1; - vertices[(3 * 5) + 0] = vx1; - vertices[(3 * 5) + 1] = vy0; - vertices[(3 * 5) + 2] = 0.0f; - vertices[(3 * 5) + 3] = glyph.s1; - vertices[(3 * 5) + 4] = glyph.t0; - glyphVertices.push_back(std::move(vertices)); + rasterize(text, x, y, fontSize, bold, windowWidth, windowHeight); + for (int i = 0; i < glyphVertices.size(); i++) { + const Glyph &glyph = glyphs[i]; + const std::unique_ptr &glyphVertice = glyphVertices[i]; vertexArrayObjects.push_back(0); vertexBufferObjects.push_back(0); elementBufferObjects.push_back(0); @@ -55,7 +22,7 @@ TextComponent::TextComponent(const std::string &text, const int x, const int y, glBindVertexArray(vertexArrayObjects.back()); glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjects.back()); - glBufferData(GL_ARRAY_BUFFER, ((3 + 2) * 4) * sizeof(float), glyphVertices.back().get(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, ((3 + 2) * 4) * sizeof(float), glyphVertice.get(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferObjects.back()); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); @@ -83,6 +50,50 @@ TextComponent::~TextComponent() { glDeleteTextures(1, &textures[i]); } } +#include +void TextComponent::rasterize(const std::string &text, const int x, const int y, const int fontSize, const bool bold, const int windowWidth, const int windowHeight) { + const std::unique_ptr textRasterizer = std::make_unique("DejaVuSerif.ttf", fontSize, 72, bold); + unsigned int glyphCount; + glyphs = textRasterizer->rasterize(text, x, y, windowWidth, windowHeight, height, glyphCount); + if (glyphs == nullptr) { + return; + } + + glyphVertices.clear(); + for (int i = 0; i < glyphCount; i++) { + const Glyph &glyph = glyphs[i]; + + float vx0 = glyph.x0; + float vy0 = glyph.y0; + float vx1 = glyph.x1; + float vy1 = glyph.y1; + pointToViewport(vx0, vy0, windowWidth, windowHeight); + pointToViewport(vx1, vy1, windowWidth, windowHeight); + + std::unique_ptr vertices = std::make_unique(20); + vertices[(0 * 5) + 0] = vx0; + vertices[(0 * 5) + 1] = vy0; + vertices[(0 * 5) + 2] = 0.0f; + vertices[(0 * 5) + 3] = glyph.s0; + vertices[(0 * 5) + 4] = glyph.t0; + vertices[(1 * 5) + 0] = vx0; + vertices[(1 * 5) + 1] = vy1; + vertices[(1 * 5) + 2] = 0.0f; + vertices[(1 * 5) + 3] = glyph.s0; + vertices[(1 * 5) + 4] = glyph.t1; + vertices[(2 * 5) + 0] = vx1; + vertices[(2 * 5) + 1] = vy1; + vertices[(2 * 5) + 2] = 0.0f; + vertices[(2 * 5) + 3] = glyph.s1; + vertices[(2 * 5) + 4] = glyph.t1; + vertices[(3 * 5) + 0] = vx1; + vertices[(3 * 5) + 1] = vy0; + vertices[(3 * 5) + 2] = 0.0f; + vertices[(3 * 5) + 3] = glyph.s1; + vertices[(3 * 5) + 4] = glyph.t0; + glyphVertices.push_back(std::move(vertices)); + } +} void TextComponent::render() { if (verticesDirty) { @@ -99,17 +110,8 @@ void TextComponent::render() { } } -void TextComponent::resize(const float sx, const float sy) { - for (int i = 0; i < glyphVertices.size(); i++) { - glyphVertices[i][(0 * 5) + 0] = ((glyphVertices[i][(0 * 5) + 0] + 1) / sx) - 1; - glyphVertices[i][(0 * 5) + 1] = ((glyphVertices[i][(0 * 5) + 1] + 1) / sy) - 1; - glyphVertices[i][(1 * 5) + 0] = ((glyphVertices[i][(1 * 5) + 0] + 1) / sx) - 1; - glyphVertices[i][(1 * 5) + 1] = ((glyphVertices[i][(1 * 5) + 1] + 1) / sy) - 1; - glyphVertices[i][(2 * 5) + 0] = ((glyphVertices[i][(2 * 5) + 0] + 1) / sx) - 1; - glyphVertices[i][(2 * 5) + 1] = ((glyphVertices[i][(2 * 5) + 1] + 1) / sy) - 1; - glyphVertices[i][(3 * 5) + 0] = ((glyphVertices[i][(3 * 5) + 0] + 1) / sx) - 1; - glyphVertices[i][(3 * 5) + 1] = ((glyphVertices[i][(3 * 5) + 1] + 1) / sy) - 1; - } +void TextComponent::resize(const int x, const int y, const int windowWidth, const int windowHeight) { + rasterize(text, x, y, fontSize, bold, windowWidth, windowHeight); verticesDirty = true; } diff --git a/src/graphics/opengl/components/TextComponent.h b/src/graphics/opengl/components/TextComponent.h index bc6b235..4ac9202 100644 --- a/src/graphics/opengl/components/TextComponent.h +++ b/src/graphics/opengl/components/TextComponent.h @@ -2,6 +2,7 @@ #define TEXTCOMPONENT_H #include +#include "../../text/TextRasterizer.h" #include "Component.h" #include #include @@ -9,15 +10,18 @@ class TextComponent : public Component { private: + std::string text; float x; float y; - float width; + int fontSize; + bool bold; bool verticesDirty = false; const unsigned int indices[6] = { 0, 1, 2, 0, 2, 3 }; unsigned char data[1024][1024][4]; + std::unique_ptr glyphs; std::vector> glyphVertices; std::vector vertexArrayObjects; std::vector vertexBufferObjects; @@ -26,8 +30,9 @@ private: public: TextComponent(const std::string &text, const int x, const int y, const int fontSize, const bool bold,const int windowWidth, const int windowHeight); ~TextComponent(); + void rasterize(const std::string &text, const int x, const int y, const int fontSize, const bool bold, const int windowWidth, const int windowHeight); void render(); - void resize(const float sx, const float sy); + void resize(const int x, const int y, const int windowWidth, const int windowHeight); void pointToViewport(float &x, float &y, const int windowWidth, const int windowHeight) const; }; diff --git a/src/graphics/text/TextRasterizer.cpp b/src/graphics/text/TextRasterizer.cpp index 074fc14..04a7674 100644 --- a/src/graphics/text/TextRasterizer.cpp +++ b/src/graphics/text/TextRasterizer.cpp @@ -36,7 +36,7 @@ TextRasterizer::~TextRasterizer() { FT_Done_FreeType(lib); } -std::unique_ptr TextRasterizer::rasterize(const std::string &text, const int x, const int y, float &height, unsigned int &glyphCount) const { +std::unique_ptr TextRasterizer::rasterize(const std::string &text, const int x, const int y, const int windowWidth, const int windowHeight, float &height, unsigned int &glyphCount) const { hb_buffer_reset(buffer); hb_buffer_set_direction(buffer, HB_DIRECTION_LTR); hb_buffer_set_language(buffer, hb_language_from_string("en", 2)); @@ -94,7 +94,7 @@ std::unique_ptr TextRasterizer::rasterize(const std::string &text cx += xa; cy += ya; - if (glyphs[i].x1 >= 1920) { + if (glyphs[i].x1 >= windowWidth) { glyphs[i].x0 -= cx; glyphs[i].y0 -= std::ceil(1.2f * fontSize); // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height glyphs[i].x1 -= cx; @@ -103,7 +103,7 @@ std::unique_ptr TextRasterizer::rasterize(const std::string &text cy -= std::ceil(1.2f * fontSize); } } - cy -= std::ceil(1.2f * fontSize); // 1.2 scalar from https://developer.mozilla.org/en-US/docs/Web/CSS/line-height + cy -= std::ceil(1.2f * fontSize); height = y - cy; diff --git a/src/graphics/text/TextRasterizer.h b/src/graphics/text/TextRasterizer.h index 37e7e0d..4852fda 100644 --- a/src/graphics/text/TextRasterizer.h +++ b/src/graphics/text/TextRasterizer.h @@ -26,7 +26,7 @@ private: public: TextRasterizer(const std::string &fontPath, const int size, const int resolution, const bool bold); ~TextRasterizer(); - std::unique_ptr rasterize(const std::string &text, const int x, const int y, float &height, unsigned int &glyphCount) const; + std::unique_ptr rasterize(const std::string &text, const int x, const int y, const int windowWidth, const int windowHeight, float &height, unsigned int &glyphCount) const; const bool isUnicodeBMP(const FT_Face &face) const; FT_Library lib; hb_font_t *font; diff --git a/src/html/elements/H1Element.cpp b/src/html/elements/H1Element.cpp index 04be4f1..b72fb00 100644 --- a/src/html/elements/H1Element.cpp +++ b/src/html/elements/H1Element.cpp @@ -3,6 +3,11 @@ #include std::unique_ptr H1Element::render(const Node &node, int y, int windowWidth, int windowHeight) { - TextNode *textNode = dynamic_cast(node.children[0].get()); - return std::make_unique(textNode->text, 0, y, 24, true, windowWidth, windowHeight); + if (!node.children.empty()) { + TextNode *textNode = dynamic_cast(node.children[0].get()); + if (textNode) { + return std::make_unique(textNode->text, 0, y, 24, true, windowWidth, windowHeight); + } + } + return nullptr; } diff --git a/src/html/elements/H2Element.cpp b/src/html/elements/H2Element.cpp index 3ba9e15..4b81a8e 100644 --- a/src/html/elements/H2Element.cpp +++ b/src/html/elements/H2Element.cpp @@ -3,6 +3,11 @@ #include std::unique_ptr H2Element::render(const Node &node, int y, int windowWidth, int windowHeight) { - TextNode *textNode = dynamic_cast(node.children[0].get()); - return std::make_unique(textNode->text, 0, y, 18, true, windowWidth, windowHeight); + if (!node.children.empty()) { + TextNode *textNode = dynamic_cast(node.children[0].get()); + if (textNode) { + return std::make_unique(textNode->text, 0, y, 18, true, windowWidth, windowHeight); + } + } + return nullptr; } diff --git a/src/html/elements/H3Element.cpp b/src/html/elements/H3Element.cpp index bbed914..7262cfb 100644 --- a/src/html/elements/H3Element.cpp +++ b/src/html/elements/H3Element.cpp @@ -3,6 +3,11 @@ #include std::unique_ptr H3Element::render(const Node &node, int y, int windowWidth, int windowHeight) { - TextNode *textNode = dynamic_cast(node.children[0].get()); - return std::make_unique(textNode->text, 0, y, 14, true, windowWidth, windowHeight); // Should be 14.04pt + if (!node.children.empty()) { + TextNode *textNode = dynamic_cast(node.children[0].get()); + if (textNode) { + return std::make_unique(textNode->text, 0, y, 14, true, windowWidth, windowHeight); // Should be 14.04pt + } + } + return nullptr; } diff --git a/src/html/elements/LIElement.cpp b/src/html/elements/LIElement.cpp index 42afcd8..093d555 100644 --- a/src/html/elements/LIElement.cpp +++ b/src/html/elements/LIElement.cpp @@ -3,6 +3,11 @@ #include std::unique_ptr LIElement::render(const Node &node, int y, int windowWidth, int windowHeight) { - TextNode *textNode = dynamic_cast(node.children[0].get()); - return std::make_unique("• " + textNode->text, 0, y, 12, false, windowWidth, windowHeight); + if (!node.children.empty()) { + TextNode *textNode = dynamic_cast(node.children[0].get()); + if (textNode) { + return std::make_unique("• " + textNode->text, 0, y, 12, false, windowWidth, windowHeight); + } + } + return nullptr; } diff --git a/src/html/elements/PElement.cpp b/src/html/elements/PElement.cpp index 3249a6f..5aa4db5 100644 --- a/src/html/elements/PElement.cpp +++ b/src/html/elements/PElement.cpp @@ -3,6 +3,11 @@ #include std::unique_ptr PElement::render(const Node &node, int y, int windowWidth, int windowHeight) { - TextNode *textNode = dynamic_cast(node.children[0].get()); - return std::make_unique(textNode->text, 0, y, 12, false, windowWidth, windowHeight); + if (!node.children.empty()) { + TextNode *textNode = dynamic_cast(node.children[0].get()); + if (textNode) { + return std::make_unique(textNode->text, 0, y, 12, false, windowWidth, windowHeight); + } + } + return nullptr; }