bool TextStyleBuilder::prepareLabel(TextStyle::Parameters& _params, Label::Type _type) {

    if (_params.text.empty() || _params.fontSize <= 0.f) {
        LOGD("invalid params: '%s' %f", _params.text.c_str(), _params.fontSize);
        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;
    }

    // Scale factor by which the texture glyphs are scaled to match fontSize
    _params.fontScale = _params.fontSize / _params.font->size();

    // Stroke width is normalized by the distance of the SDF spread, then
    // scaled to 255 and packed into the "alpha" channel of stroke.
    // Maximal strokeWidth is 3px, attribute is normalized to 0-1 range.

    auto ctx = m_style.context();

    uint32_t strokeAttrib = std::max(_params.strokeWidth / ctx->maxStrokeWidth() * 255.f, 0.f);
    if (strokeAttrib > 255) {
        LOGN("stroke_width too large: %f / %f", _params.strokeWidth, strokeAttrib/255.f);
        strokeAttrib = 255;
    }
    m_attributes.stroke = (_params.strokeColor & 0x00ffffff) + (strokeAttrib << 24);
    m_attributes.fill = _params.fill;
    m_attributes.fontScale = _params.fontScale * 64.f;
    if (m_attributes.fontScale > 255) {
        LOGN("Too large font scale %f, maximal scale is 4", _params.fontScale);
        m_attributes.fontScale = 255;
    }
    m_attributes.quadsStart = m_quads.size();

    m_attributes.textRanges = TextRange{};

    glm::vec2 bbox(0);
    if (ctx->layoutText(_params, *renderText, m_quads, m_atlasRefs, bbox, m_attributes.textRanges)) {
        m_attributes.width = bbox.x;
        m_attributes.height = bbox.y;
        return true;
    }
    return false;
}
Exemple #2
0
void LayoutMenuList::updateOptionsWidth() const {
  float maxOptionWidth = 0;

  for (const auto& option : selectElement()->optionList()) {
    String text = option->textIndentedToRespectGroupLabel();
    const ComputedStyle* itemStyle =
        option->computedStyle() ? option->computedStyle() : style();
    applyTextTransform(itemStyle, text, ' ');
    // We apply SELECT's style, not OPTION's style because m_optionsWidth is
    // used to determine intrinsic width of the menulist box.
    TextRun textRun = constructTextRun(style()->font(), text, *style());
    maxOptionWidth = std::max(maxOptionWidth, style()->font().width(textRun));
  }
  m_optionsWidth = static_cast<int>(ceilf(maxOptionWidth));
}
Exemple #3
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;
}
Exemple #4
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;
}