Beispiel #1
0
int TextBuffer::applyWordWrapping(std::vector<FONSquad>& _quads,
                                  const TextStyle::Parameters& _params,
                                  const FontContext::FontMetrics& _metrics,
                                  Label::Type _type, glm::vec2* _bbox,
                                  std::vector<TextBuffer::WordBreak>& _wordBreaks) {
    struct LineQuad {
        std::vector<FONSquad*> quads;
        float length = 0.0f;
    };

    float yOffset = 0.f, xOffset = 0.f;
    int nLine = 1;

    std::vector<LineQuad> lines;

    if (_params.wordWrap < _params.text.length() && _type != Label::Type::line) {
       _wordBreaks = findWords(_params.text);
    } else {
        for (auto& q : _quads) {
            _bbox->x = std::max(_bbox->x, q.x1);
        }
    }

    lines.push_back(LineQuad()); // atleast one line

    // Apply word wrapping based on the word breaks
    for (int iWord = 0; iWord < int(_wordBreaks.size()); iWord++) {
        int start = _wordBreaks[iWord].start;
        int end = _wordBreaks[iWord].end;
        size_t wordSize = end - start + 1;

        auto& lastLineQuads = lines[nLine - 1].quads;

        // Check if quads need to be added to next line?
        if (iWord > 0 && (lastLineQuads.size() + wordSize) > size_t(_params.maxLineWidth)) {
            xOffset = 0.0f;
            auto& quad = _quads[start];
            auto& prevQuad = lines[nLine - 1].quads.front();

            float baseLength = quad.x0 - prevQuad->x0;
            yOffset += _metrics.lineHeight;
            xOffset -= (baseLength);
            lines.push_back(LineQuad());
            nLine++;
        }

        for (int i = start; i <= end; i++) {
            auto& q = _quads[i];

            q.x0 += xOffset;
            q.x1 += xOffset;
            q.y0 += yOffset;
            q.y1 += yOffset;

            lines[nLine - 1].quads.push_back(&q);
            lines[nLine - 1].length = q.x1;

            // Adjust the bounding box on x
            _bbox->x = std::max(_bbox->x, q.x1);
        }
    }

    // Adjust the bounding box on y
    _bbox->y = _metrics.lineHeight * nLine;

    float bboxOffsetY = _bbox->y * 0.5f - _metrics.lineHeight - _metrics.descender;

    // Apply justification
    for (const auto& line : lines) {
        float paddingRight = _bbox->x - line.length;
        float padding = 0;

        switch(_params.align) {
            case TextLabelProperty::Align::left: padding = 0.f; break;
            case TextLabelProperty::Align::right: padding = paddingRight; break;
            case TextLabelProperty::Align::center: padding = paddingRight * 0.5f; break;
        }

        for (auto quad : line.quads) {
            quad->x0 += padding;
            quad->x1 += padding;
            quad->y0 -= bboxOffsetY;
            quad->y1 -= bboxOffsetY;
        }
    }

    return nLine;
}
Beispiel #2
0
int TextBuffer::Builder::applyWordWrapping(std::vector<FONSquad>& _quads,
                                           const TextStyle::Parameters& _params,
                                           const FontContext::FontMetrics& _metrics) {
    struct LineQuad {
        std::vector<FONSquad*> quads;
        float length = 0.0f;
    };

    float yOffset = 0.f, xOffset = 0.f;
    int nLine = 1;

    std::vector<LineQuad> lines;
    if (_params.wordWrap && _params.maxLineWidth < _params.text.length()) {
        findWords(_params.text, m_wordBreaks);
    } else {
        return 1;
    }

    lines.push_back(LineQuad()); // atleast one line
    float totalWidth = 0.f;

    // Apply word wrapping based on the word breaks
    for (int iWord = 0; iWord < int(m_wordBreaks.size()); iWord++) {
        int start = m_wordBreaks[iWord].start;
        int end = m_wordBreaks[iWord].end;
        size_t wordSize = end - start + 1;

        auto& lastLineQuads = lines[nLine - 1].quads;

        // Check if quads need to be added to next line?
        if (iWord > 0 && (lastLineQuads.size() + wordSize) > size_t(_params.maxLineWidth)) {
            xOffset = 0.0f;
            auto& quad = _quads[start];
            auto& prevQuad = lines[nLine - 1].quads.front();

            float baseLength = quad.x0 - prevQuad->x0;
            yOffset += _metrics.lineHeight;
            xOffset -= (baseLength);
            lines.push_back(LineQuad());
            nLine++;
        }

        for (int i = start; i <= end; i++) {
            auto& q = _quads[i];

            q.x0 += xOffset;
            q.x1 += xOffset;
            q.y0 += yOffset;
            q.y1 += yOffset;

            lines[nLine - 1].quads.push_back(&q);
            lines[nLine - 1].length = q.x1;

            totalWidth = std::max(totalWidth, q.x1);
        }
    }

    // Apply justification
    for (const auto& line : lines) {
        float paddingRight = totalWidth - line.length;
        float padding = 0;

        switch(_params.align) {
            case TextLabelProperty::Align::left: padding = 0.f; break;
            case TextLabelProperty::Align::right: padding = paddingRight; break;
            case TextLabelProperty::Align::center: padding = paddingRight * 0.5f; break;
        }

        for (auto quad : line.quads) {
            quad->x0 += padding;
            quad->x1 += padding;
        }
    }

    return nLine;
}