Esempio n. 1
0
bool TextBuffer::addLabel(const TextStyle::Parameters& _params, Label::Transform _transform,
                          Label::Type _type, FontContext& _fontContext) {

    if (_params.fontId < 0 || _params.fontSize <= 0.f || _params.text.size() == 0) {
        return false;
    }

    /// Apply text transforms
    const std::string* renderText;
    std::string text;

    if (_params.transform == TextLabelProperty::Transform::none) {
        renderText = &_params.text;
    } else {
        text = applyTextTransform(_params, _params.text);
        renderText = &text;
    }

    if (!_fontContext.lock()) {
        return false;
    }

    /// Rasterize the glyphs
    auto& quads = _fontContext.rasterize(*renderText, _params.fontId,
                                         _params.fontSize, _params.blurSpread);

    size_t numGlyphs = quads.size();

    if (numGlyphs == 0) {
        _fontContext.unlock();
        return false;
    }

    auto& vertices = m_vertices[0];
    int vertexOffset = vertices.size();
    int numVertices = numGlyphs * 4;

    // Stroke width is normalized by the distance of the SDF spread, then scaled
    // to a char, then packed into the "alpha" channel of stroke. The .25 scaling
    // probably has to do with how the SDF is generated, but honestly I'm not sure
    // what it represents.
    uint32_t strokeWidth = _params.strokeWidth / _params.blurSpread * 255. * .25;
    uint32_t stroke = (_params.strokeColor & 0x00ffffff) + (strokeWidth << 24);

    FontContext::FontMetrics metrics = _fontContext.getMetrics();

    /// Apply word wrapping
    glm::vec2 bbox;
    std::vector<TextBuffer::WordBreak> wordBreaks;
    int nLine = applyWordWrapping(quads, _params, _fontContext.getMetrics(), _type, &bbox, wordBreaks);

    /// Generate the quads
    for (int i = 0; i < int(quads.size()); ++i) {
        if (wordBreaks.size() > 0) {
            bool skip = false;
            // Skip spaces/CR quads
            for (int j = 0; j < int(wordBreaks.size()) - 1; ++j) {
                const auto& b1 = wordBreaks[j];
                const auto& b2 = wordBreaks[j + 1];
                if (i >= b1.end + 1 && i <= b2.start - 1) {
                    numVertices -= 4;
                    skip = true;
                    break;
                }
            }
            if (skip) { continue; }
        }

        const auto& q = quads[i];
        vertices.push_back({{q.x0, q.y0}, {q.s0, q.t0}, {-1.f, -1.f, 0.f}, _params.fill, stroke});
        vertices.push_back({{q.x0, q.y1}, {q.s0, q.t1}, {-1.f,  1.f, 0.f}, _params.fill, stroke});
        vertices.push_back({{q.x1, q.y0}, {q.s1, q.t0}, { 1.f, -1.f, 0.f}, _params.fill, stroke});
        vertices.push_back({{q.x1, q.y1}, {q.s1, q.t1}, { 1.f,  1.f, 0.f}, _params.fill, stroke});
    }

    _fontContext.unlock();

    m_labels.emplace_back(new TextLabel(_transform, _type, bbox, *this, { vertexOffset, numVertices },
                                        _params.labelOptions, metrics, nLine, _params.anchor));

    // TODO: change this in TypeMesh::adVertices()
    m_nVertices = vertices.size();

    return true;
}
Esempio n. 2
0
bool TextBuffer::Builder::prepareLabel(FontContext& _fontContext,
                                       const TextStyle::Parameters& _params) {

    if (_params.fontId < 0 || _params.fontSize <= 0.f || _params.text.size() == 0) {
        return false;
    }

    /// Apply text transforms
    const std::string* renderText;
    std::string text;

    if (_params.transform == TextLabelProperty::Transform::none) {
        renderText = &_params.text;
    } else {
        text = applyTextTransform(_params, _params.text);
        renderText = &text;
    }

    if (!_fontContext.lock()) {
        return false;
    }

    /// Rasterize the glyphs
    auto& quads = _fontContext.rasterize(*renderText, _params.fontId,
                                         _params.fontSize, _params.blurSpread);

    size_t numGlyphs = quads.size();

    if (numGlyphs == 0) {
        _fontContext.unlock();
        return false;
    }

    // Stroke width is normalized by the distance of the SDF spread, then scaled
    // to a char, then packed into the "alpha" channel of stroke. The .25 scaling
    // probably has to do with how the SDF is generated, but honestly I'm not sure
    // what it represents.
    uint32_t strokeWidth = _params.strokeWidth / _params.blurSpread * 255. * .25;
    uint32_t stroke = (_params.strokeColor & 0x00ffffff) + (strokeWidth << 24);

    m_metrics = _fontContext.getMetrics();
    m_bbox = glm::vec2(0);

    /// Apply word wrapping
    int nLine = 1;

    m_wordBreaks.clear();
    nLine = applyWordWrapping(quads, _params, m_metrics);

    /// Generate the quads
    float yMin = std::numeric_limits<float>::max();
    float xMin = std::numeric_limits<float>::max();

    m_scratchVertices.clear();

    for (int i = 0; i < int(quads.size()); ++i) {
        if (m_wordBreaks.size() > 0) {
            bool skip = false;
            // Skip spaces/CR quads
            for (int j = 0; j < int(m_wordBreaks.size()) - 1; ++j) {
                const auto& b1 = m_wordBreaks[j];
                const auto& b2 = m_wordBreaks[j + 1];
                if (i >= b1.end + 1 && i <= b2.start - 1) {
                    skip = true;
                    break;
                }
            }
            if (skip) { continue; }
        }

        const auto& q = quads[i];
        m_scratchVertices.push_back({{q.x0, q.y0}, {q.s0, q.t0}, _params.fill, stroke});
        m_scratchVertices.push_back({{q.x0, q.y1}, {q.s0, q.t1}, _params.fill, stroke});
        m_scratchVertices.push_back({{q.x1, q.y0}, {q.s1, q.t0}, _params.fill, stroke});
        m_scratchVertices.push_back({{q.x1, q.y1}, {q.s1, q.t1}, _params.fill, stroke});

        yMin = std::min(yMin, q.y0);
        xMin = std::min(xMin, q.x0);

        m_bbox.x = std::max(m_bbox.x, q.x1);
        m_bbox.y = std::max(m_bbox.y, std::abs(yMin - q.y1));
    }

    m_bbox.x -= xMin;
    m_quadsLocalOrigin = { xMin, quads[0].y0 };
    m_numLines = nLine;

    _fontContext.unlock();

    return true;
}