<commit_before>#include "fontStyle.h"
#define GLFONTSTASH_IMPLEMENTATION
#include "glfontstash.h"

FontStyle::FontStyle(const std::string& _fontFile, std::string _name, float _fontSize, bool _sdf, GLenum _drawMode)
: Style(_name, _drawMode), m_fontSize(_fontSize), m_sdf(_sdf) {

    constructVertexLayout();
    constructShaderProgram();
    initFontContext(_fontFile);
}

FontStyle::~FontStyle() {
    glfonsDelete(m_fontContext->m_fsContext);

    for (auto& pair : m_transformTileTextures) {
        pair.second->destroy();
    }
}

void FontStyle::constructVertexLayout() {
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 2, GL_FLOAT, false, 0},
        {"a_texCoord", 2, GL_FLOAT, false, 0},
        {"a_fsid", 1, GL_FLOAT, false, 0},
    }));
}

void FontStyle::constructShaderProgram() {
    std::string frag = m_sdf ? "sdf.fs" : "text.fs";

    std::string vertShaderSrcStr = stringFromResource("text.vs");
    std::string fragShaderSrcStr = stringFromResource(frag.c_str());

    m_shaderProgram = std::make_shared<ShaderProgram>();

    if (!m_shaderProgram->buildFromSourceStrings(fragShaderSrcStr, vertShaderSrcStr)) {
        logMsg("[FontStyle] Error building text shader program\n");
    }
}

void FontStyle::buildPoint(Point& _point, std::string& _layer, Properties& _props, VboMesh& _mesh) {

}

void FontStyle::buildLine(Line& _line, std::string& _layer, Properties& _props, VboMesh& _mesh) {
    std::vector<float> vertData;
    int nVerts = 0;

    fonsSetSize(m_fontContext->m_fsContext, m_fontSize * m_pixelScale);
    fonsSetFont(m_fontContext->m_fsContext, m_font);

    if(m_sdf) {
        float blurSpread = 2.5;
        fonsSetBlur(m_fontContext->m_fsContext, blurSpread);
        fonsSetBlurType(m_fontContext->m_fsContext, FONS_EFFECT_DISTANCE_FIELD);
    }

    if (_layer.compare("roads") == 0) {
        for (auto prop : _props.stringProps) {
            if (prop.first.compare("name") == 0 && _line.size() == 2) { // don't treat polylines

                glm::dvec2 p1 = glm::dvec2(_line[0]);
                glm::dvec2 p2 = glm::dvec2(_line[1]);
                glm::dvec2 p1p2 = p1 - p2;

                if(glm::length(p1p2) < 0.5) { // some random label discard for now
                    return;
                }

                p1p2 = glm::normalize(p1p2);
                float r = (float) atan2(p1p2.x, p1p2.y) + M_PI_2;

                double offset = 1;
                if (r > M_PI_2 || r < -M_PI_2) {
                    r += M_PI;
                    offset = -1;
                }

                fsuint textId;
                glfonsGenText(m_fontContext->m_fsContext, 1, &textId);

                glm::dvec2 position = (p1 + p2) / 2.0 + p1p2 * 0.2 * offset;

                // FUTURE: label logic
                // 1. project label on screen and compute its bbox, to do so we need the view and label model matrix
                // 2. ask any kind of label manager to perform label discards

                std::unique_ptr<Label> label(new Label {
                    m_fontContext,
                    textId,
                    prop.second.c_str(),
                    position,   // world position
                    1.0,        // alpha
                    r           // rotation
                });

                if (m_processedTile->addLabel(*this, std::move(label))) { // could potentially refuse to add label

                    logMsg("[FontStyle] Rasterize label: %s, angle: %f\n", prop.second.c_str(), r * (180/M_PI));

                    glfonsRasterize(m_fontContext->m_fsContext, textId, prop.second.c_str(), FONS_EFFECT_NONE);
                }
            }
        }
    }

    fonsClearState(m_fontContext->m_fsContext);

    if (glfonsVertices(m_fontContext->m_fsContext, &vertData, &nVerts)) {
        _mesh.addVertices((GLbyte*)vertData.data(), nVerts);
    }
}

void FontStyle::buildPolygon(Polygon& _polygon, std::string& _layer, Properties& _props, VboMesh& _mesh) {

}

void FontStyle::prepareDataProcessing(MapTile& _tile) {
    m_fontContext->m_contextMutex->lock();

    m_processedTile = &_tile;

    fsuint buffer;
    
    int transformTextureSize = 2; // start with a transform texture of size 2x4 

    glfonsBufferCreate(m_fontContext->m_fsContext, transformTextureSize, &buffer);
    _tile.setTextBuffer(*this, buffer);
    glfonsBindBuffer(m_fontContext->m_fsContext, buffer);
}

void FontStyle::finishDataProcessing(MapTile& _tile) {
    glfonsBindBuffer(m_fontContext->m_fsContext, 0);

    m_processedTile = nullptr;

    m_fontContext->m_contextMutex->unlock();
}

void FontStyle::setupTile(const std::shared_ptr<MapTile>& _tile) {
    std::unique_ptr<Texture>& texture = m_transformTileTextures[_tile->getID()];

    texture->bind();
    
    // transform texture
    m_shaderProgram->setUniformi("u_transforms", texture->getTextureSlot()); 
    // resolution of the transform texture
    m_shaderProgram->setUniformf("u_tresolution", texture->getWidth(), texture->getHeight()); 
}

void FontStyle::setupFrame(const std::shared_ptr<View>& _view) {
    float projectionMatrix[16] = {0};

    glfonsProjection(m_fontContext->m_fsContext, projectionMatrix);

    for (auto& pair : m_transformTileTextures) {
        pair.second->update();
    }

    m_atlas->update();
    m_atlas->bind();<commit_msg>move texture updates to setup tile<commit_after>#include "fontStyle.h"
#define GLFONTSTASH_IMPLEMENTATION
#include "glfontstash.h"

FontStyle::FontStyle(const std::string& _fontFile, std::string _name, float _fontSize, bool _sdf, GLenum _drawMode)
: Style(_name, _drawMode), m_fontSize(_fontSize), m_sdf(_sdf) {

    constructVertexLayout();
    constructShaderProgram();
    initFontContext(_fontFile);
}

FontStyle::~FontStyle() {
    glfonsDelete(m_fontContext->m_fsContext);

    for (auto& pair : m_transformTileTextures) {
        pair.second->destroy();
    }
}

void FontStyle::constructVertexLayout() {
    m_vertexLayout = std::shared_ptr<VertexLayout>(new VertexLayout({
        {"a_position", 2, GL_FLOAT, false, 0},
        {"a_texCoord", 2, GL_FLOAT, false, 0},
        {"a_fsid", 1, GL_FLOAT, false, 0},
    }));
}

void FontStyle::constructShaderProgram() {
    std::string frag = m_sdf ? "sdf.fs" : "text.fs";

    std::string vertShaderSrcStr = stringFromResource("text.vs");
    std::string fragShaderSrcStr = stringFromResource(frag.c_str());

    m_shaderProgram = std::make_shared<ShaderProgram>();

    if (!m_shaderProgram->buildFromSourceStrings(fragShaderSrcStr, vertShaderSrcStr)) {
        logMsg("[FontStyle] Error building text shader program\n");
    }
}

void FontStyle::buildPoint(Point& _point, std::string& _layer, Properties& _props, VboMesh& _mesh) {

}

void FontStyle::buildLine(Line& _line, std::string& _layer, Properties& _props, VboMesh& _mesh) {
    std::vector<float> vertData;
    int nVerts = 0;

    fonsSetSize(m_fontContext->m_fsContext, m_fontSize * m_pixelScale);
    fonsSetFont(m_fontContext->m_fsContext, m_font);

    if(m_sdf) {
        float blurSpread = 2.5;
        fonsSetBlur(m_fontContext->m_fsContext, blurSpread);
        fonsSetBlurType(m_fontContext->m_fsContext, FONS_EFFECT_DISTANCE_FIELD);
    }

    if (_layer.compare("roads") == 0) {
        for (auto prop : _props.stringProps) {
            if (prop.first.compare("name") == 0 && _line.size() == 2) { // don't treat polylines

                glm::dvec2 p1 = glm::dvec2(_line[0]);
                glm::dvec2 p2 = glm::dvec2(_line[1]);
                glm::dvec2 p1p2 = p1 - p2;

                if(glm::length(p1p2) < 0.5) { // some random label discard for now
                    return;
                }

                p1p2 = glm::normalize(p1p2);
                float r = (float) atan2(p1p2.x, p1p2.y) + M_PI_2;

                double offset = 1;
                if (r > M_PI_2 || r < -M_PI_2) {
                    r += M_PI;
                    offset = -1;
                }

                fsuint textId;
                glfonsGenText(m_fontContext->m_fsContext, 1, &textId);

                glm::dvec2 position = (p1 + p2) / 2.0 + p1p2 * 0.2 * offset;

                // FUTURE: label logic
                // 1. project label on screen and compute its bbox, to do so we need the view and label model matrix
                // 2. ask any kind of label manager to perform label discards

                std::unique_ptr<Label> label(new Label {
                    m_fontContext,
                    textId,
                    prop.second.c_str(),
                    position,   // world position
                    1.0,        // alpha
                    r           // rotation
                });

                if (m_processedTile->addLabel(*this, std::move(label))) { // could potentially refuse to add label

                    logMsg("[FontStyle] Rasterize label: %s, angle: %f\n", prop.second.c_str(), r * (180/M_PI));

                    glfonsRasterize(m_fontContext->m_fsContext, textId, prop.second.c_str(), FONS_EFFECT_NONE);
                }
            }
        }
    }

    fonsClearState(m_fontContext->m_fsContext);

    if (glfonsVertices(m_fontContext->m_fsContext, &vertData, &nVerts)) {
        _mesh.addVertices((GLbyte*)vertData.data(), nVerts);
    }
}

void FontStyle::buildPolygon(Polygon& _polygon, std::string& _layer, Properties& _props, VboMesh& _mesh) {

}

void FontStyle::prepareDataProcessing(MapTile& _tile) {
    m_fontContext->m_contextMutex->lock();

    m_processedTile = &_tile;

    fsuint buffer;
    
    int transformTextureSize = 2; // start with a transform texture of size 2x4 

    glfonsBufferCreate(m_fontContext->m_fsContext, transformTextureSize, &buffer);
    _tile.setTextBuffer(*this, buffer);
    glfonsBindBuffer(m_fontContext->m_fsContext, buffer);
}

void FontStyle::finishDataProcessing(MapTile& _tile) {
    glfonsBindBuffer(m_fontContext->m_fsContext, 0);

    m_processedTile = nullptr;

    m_fontContext->m_contextMutex->unlock();
}

void FontStyle::setupTile(const std::shared_ptr<MapTile>& _tile) {
    std::unique_ptr<Texture>& texture = m_transformTileTextures[_tile->getID()];

    if(texture) {
        texture->update();
        texture->bind();
    
        // transform texture
        m_shaderProgram->setUniformi("u_transforms", texture->getTextureSlot());
        // resolution of the transform texture
        m_shaderProgram->setUniformf("u_tresolution", texture->getWidth(), texture->getHeight());
    }
}

void FontStyle::setupFrame(const std::shared_ptr<View>& _view) {
    float projectionMatrix[16] = {0};

    glfonsProjection(m_fontContext->m_fsContext, projectionMatrix);

    m_atlas->update();
    m_atlas->bind();
{'fraction_non_alphanumeric': 0.1261791351452321, 'fraction_numerical': 0.012515176987017838, 'mean_word_length': 2.672153635116598, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2106388', 'n_tokens_mistral': 3584, 'n_tokens_neox': 3415, 'n_words': 667}