Browse Source

Responsive text

pull/1/head
gyroninja 5 years ago
parent
commit
ada1e829c1
  1. 10
      src/graphics/opengl/Window.cpp
  2. 5
      src/graphics/opengl/Window.h
  3. 106
      src/graphics/opengl/components/TextComponent.cpp
  4. 9
      src/graphics/opengl/components/TextComponent.h
  5. 6
      src/graphics/text/TextRasterizer.cpp
  6. 2
      src/graphics/text/TextRasterizer.h
  7. 9
      src/html/elements/H1Element.cpp
  8. 9
      src/html/elements/H2Element.cpp
  9. 9
      src/html/elements/H3Element.cpp
  10. 9
      src/html/elements/LIElement.cpp
  11. 9
      src/html/elements/PElement.cpp

10
src/graphics/opengl/Window.cpp

@ -50,16 +50,16 @@ bool Window::initGLFW() { @@ -50,16 +50,16 @@ bool Window::initGLFW() {
glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
Window *thiz = reinterpret_cast<Window*>(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> &boxComponent : thiz->boxComponents) {
boxComponent->resize(width, height);
}
thiz->y = 950;
for (const std::unique_ptr<Component> &component : thiz->components) {
TextComponent *textComponent = dynamic_cast<TextComponent*>(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() { @@ -155,12 +155,12 @@ void Window::render() {
glfwSwapBuffers(window);
}
void Window::setDOM(std::shared_ptr<Node> rootNode) {
void Window::setDOM(const std::shared_ptr<Node> rootNode) {
domRootNode = rootNode;
domDirty = true;
}
void Window::drawNode(std::shared_ptr<Node> node) {
void Window::drawNode(const std::shared_ptr<Node> node) {
if (node->nodeType == NodeType::TAG) {
TagNode *tagNode = dynamic_cast<TagNode*>(node.get());
std::unique_ptr<Component> component = tagNode->render(*tagNode, y, windowWidth, windowHeight);

5
src/graphics/opengl/Window.h

@ -23,8 +23,9 @@ public: @@ -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<Node> rootNode);
void drawNode(std::shared_ptr<Node> rootNode);
void setDOM(const std::shared_ptr<Node> rootNode);
void drawNode(const std::shared_ptr<Node> rootNode);
void repositionNode(const std::shared_ptr<Node> rootNode);
GLFWwindow *window;
int windowWidth;
int windowHeight;

106
src/graphics/opengl/components/TextComponent.cpp

@ -1,50 +1,17 @@ @@ -1,50 +1,17 @@
#include "TextComponent.h"
#include "../../text/TextRasterizer.h"
#include <memory>
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> textRasterizer = std::make_unique<TextRasterizer>("DejaVuSerif.ttf", fontSize, 72, bold);
unsigned int glyphCount;
std::unique_ptr<const Glyph[]> 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<float[]> vertices = std::make_unique<float[]>(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<float[]> &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, @@ -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() { @@ -83,6 +50,50 @@ TextComponent::~TextComponent() {
glDeleteTextures(1, &textures[i]);
}
}
#include <iostream>
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> textRasterizer = std::make_unique<TextRasterizer>("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<float[]> vertices = std::make_unique<float[]>(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() { @@ -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;
}

9
src/graphics/opengl/components/TextComponent.h

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
#define TEXTCOMPONENT_H
#include <GL/glew.h>
#include "../../text/TextRasterizer.h"
#include "Component.h"
#include <array>
#include <memory>
@ -9,15 +10,18 @@ @@ -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<const Glyph[]> glyphs;
std::vector<std::unique_ptr<float[]>> glyphVertices;
std::vector<GLuint> vertexArrayObjects;
std::vector<GLuint> vertexBufferObjects;
@ -26,8 +30,9 @@ private: @@ -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;
};

6
src/graphics/text/TextRasterizer.cpp

@ -36,7 +36,7 @@ TextRasterizer::~TextRasterizer() { @@ -36,7 +36,7 @@ TextRasterizer::~TextRasterizer() {
FT_Done_FreeType(lib);
}
std::unique_ptr<const Glyph[]> TextRasterizer::rasterize(const std::string &text, const int x, const int y, float &height, unsigned int &glyphCount) const {
std::unique_ptr<const Glyph[]> 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<const Glyph[]> TextRasterizer::rasterize(const std::string &text @@ -94,7 +94,7 @@ std::unique_ptr<const Glyph[]> 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<const Glyph[]> TextRasterizer::rasterize(const std::string &text @@ -103,7 +103,7 @@ std::unique_ptr<const Glyph[]> 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;

2
src/graphics/text/TextRasterizer.h

@ -26,7 +26,7 @@ private: @@ -26,7 +26,7 @@ private:
public:
TextRasterizer(const std::string &fontPath, const int size, const int resolution, const bool bold);
~TextRasterizer();
std::unique_ptr<const Glyph[]> rasterize(const std::string &text, const int x, const int y, float &height, unsigned int &glyphCount) const;
std::unique_ptr<const Glyph[]> 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;

9
src/html/elements/H1Element.cpp

@ -3,6 +3,11 @@ @@ -3,6 +3,11 @@
#include <iostream>
std::unique_ptr<Component> H1Element::render(const Node &node, int y, int windowWidth, int windowHeight) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
return std::make_unique<TextComponent>(textNode->text, 0, y, 24, true, windowWidth, windowHeight);
if (!node.children.empty()) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
if (textNode) {
return std::make_unique<TextComponent>(textNode->text, 0, y, 24, true, windowWidth, windowHeight);
}
}
return nullptr;
}

9
src/html/elements/H2Element.cpp

@ -3,6 +3,11 @@ @@ -3,6 +3,11 @@
#include <iostream>
std::unique_ptr<Component> H2Element::render(const Node &node, int y, int windowWidth, int windowHeight) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
return std::make_unique<TextComponent>(textNode->text, 0, y, 18, true, windowWidth, windowHeight);
if (!node.children.empty()) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
if (textNode) {
return std::make_unique<TextComponent>(textNode->text, 0, y, 18, true, windowWidth, windowHeight);
}
}
return nullptr;
}

9
src/html/elements/H3Element.cpp

@ -3,6 +3,11 @@ @@ -3,6 +3,11 @@
#include <iostream>
std::unique_ptr<Component> H3Element::render(const Node &node, int y, int windowWidth, int windowHeight) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
return std::make_unique<TextComponent>(textNode->text, 0, y, 14, true, windowWidth, windowHeight); // Should be 14.04pt
if (!node.children.empty()) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
if (textNode) {
return std::make_unique<TextComponent>(textNode->text, 0, y, 14, true, windowWidth, windowHeight); // Should be 14.04pt
}
}
return nullptr;
}

9
src/html/elements/LIElement.cpp

@ -3,6 +3,11 @@ @@ -3,6 +3,11 @@
#include <iostream>
std::unique_ptr<Component> LIElement::render(const Node &node, int y, int windowWidth, int windowHeight) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
return std::make_unique<TextComponent>("" + textNode->text, 0, y, 12, false, windowWidth, windowHeight);
if (!node.children.empty()) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
if (textNode) {
return std::make_unique<TextComponent>("" + textNode->text, 0, y, 12, false, windowWidth, windowHeight);
}
}
return nullptr;
}

9
src/html/elements/PElement.cpp

@ -3,6 +3,11 @@ @@ -3,6 +3,11 @@
#include <iostream>
std::unique_ptr<Component> PElement::render(const Node &node, int y, int windowWidth, int windowHeight) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
return std::make_unique<TextComponent>(textNode->text, 0, y, 12, false, windowWidth, windowHeight);
if (!node.children.empty()) {
TextNode *textNode = dynamic_cast<TextNode*>(node.children[0].get());
if (textNode) {
return std::make_unique<TextComponent>(textNode->text, 0, y, 12, false, windowWidth, windowHeight);
}
}
return nullptr;
}

Loading…
Cancel
Save