| 356 | } |
| 357 | |
| 358 | void MutableLabel::SetText(LabelResult & result, std::string text, ref_ptr<dp::TextureManager> mng) |
| 359 | { |
| 360 | if (size_t const sz = text.size(); sz < m_maxLength) |
| 361 | { |
| 362 | /// @todo I don't see a better way to clear cached vertices from the previous frame (text value). |
| 363 | text.append(m_maxLength - sz, ' '); |
| 364 | } |
| 365 | else if (sz > m_maxLength) |
| 366 | { |
| 367 | text.erase(m_maxLength - 3); |
| 368 | text.append("..."); |
| 369 | } |
| 370 | |
| 371 | // TODO(AB): Calculate only the length for pre-cached glyphs in a simpler way? |
| 372 | m_glyphRegions.clear(); |
| 373 | m_shapedText = mng->ShapeSingleTextLine(dp::kBaseFontSizePixels, text, &m_glyphRegions); |
| 374 | |
| 375 | // TODO(AB): Reuse pre-calculated width and height? |
| 376 | // float maxHeight = m_shapedText.m_maxLineHeightInPixels; |
| 377 | // float length = m_shapedText.m_lineWidthInPixels; |
| 378 | |
| 379 | float maxHeight = 0.0f; |
| 380 | |
| 381 | std::pair minMaxXPos = {std::numeric_limits<float>::max(), std::numeric_limits<float>::lowest()}; |
| 382 | float offsetLeft = 0; |
| 383 | |
| 384 | glsl::vec2 pen = glsl::vec2(0.0, 0.0); |
| 385 | |
| 386 | ASSERT_EQUAL(m_glyphRegions.size(), m_shapedText.m_glyphs.size(), ()); |
| 387 | for (size_t i = 0; i < m_glyphRegions.size(); ++i) |
| 388 | { |
| 389 | std::array<glsl::vec2, 4> normals, maskTex; |
| 390 | dp::TextureManager::GlyphRegion const & glyph = m_glyphRegions[i]; |
| 391 | auto const & metrics = m_shapedText.m_glyphs[i]; |
| 392 | glsl::vec2 const offsets = |
| 393 | GetNormalsAndMask(glyph, metrics.m_xOffset, metrics.m_yOffset, m_textRatio, normals, maskTex); |
| 394 | |
| 395 | ASSERT_EQUAL(normals.size(), maskTex.size(), ()); |
| 396 | |
| 397 | for (size_t j = 0; j < normals.size(); ++j) |
| 398 | { |
| 399 | result.m_buffer.emplace_back(pen + normals[j], maskTex[j]); |
| 400 | auto const & back = result.m_buffer.back(); |
| 401 | if (back.m_normal.x < minMaxXPos.first) |
| 402 | { |
| 403 | minMaxXPos.first = back.m_normal.x; |
| 404 | offsetLeft = offsets.x; |
| 405 | } |
| 406 | minMaxXPos.second = std::max(minMaxXPos.second, back.m_normal.x); |
| 407 | } |
| 408 | |
| 409 | // TODO(AB): yAdvance is always zero for horizontal layouts. |
| 410 | pen += glsl::vec2(metrics.m_xAdvance * m_textRatio, metrics.m_yAdvance * m_textRatio); |
| 411 | maxHeight = std::max(maxHeight, offsets.y + glyph.GetPixelHeight() * m_textRatio); |
| 412 | } |
| 413 | |
| 414 | float const length = minMaxXPos.second - minMaxXPos.first; |
| 415 | // "- offset_left" is an approximation |
no test coverage detected