| 1374 | } |
| 1375 | |
| 1376 | std::vector<std::string> GfxRenderer::wrappedText(const int fontId, const char* text, const int maxWidth, |
| 1377 | const int maxLines, const EpdFontFamily::Style style) const { |
| 1378 | std::vector<std::string> lines; |
| 1379 | |
| 1380 | if (!text || maxWidth <= 0 || maxLines <= 0) return lines; |
| 1381 | |
| 1382 | std::string remaining = text; |
| 1383 | std::string currentLine; |
| 1384 | |
| 1385 | while (!remaining.empty()) { |
| 1386 | if (static_cast<int>(lines.size()) == maxLines - 1) { |
| 1387 | // Last available line: combine any word already started on this line with |
| 1388 | // the rest of the text, then let truncatedText fit it with an ellipsis. |
| 1389 | std::string lastContent = currentLine.empty() ? remaining : currentLine + " " + remaining; |
| 1390 | lines.push_back(truncatedText(fontId, lastContent.c_str(), maxWidth, style)); |
| 1391 | return lines; |
| 1392 | } |
| 1393 | |
| 1394 | // Find next word |
| 1395 | size_t spacePos = remaining.find(' '); |
| 1396 | std::string word; |
| 1397 | |
| 1398 | if (spacePos == std::string::npos) { |
| 1399 | word = remaining; |
| 1400 | remaining.clear(); |
| 1401 | } else { |
| 1402 | word = remaining.substr(0, spacePos); |
| 1403 | remaining.erase(0, spacePos + 1); |
| 1404 | } |
| 1405 | |
| 1406 | std::string testLine = currentLine.empty() ? word : currentLine + " " + word; |
| 1407 | |
| 1408 | if (getTextWidth(fontId, testLine.c_str(), style) <= maxWidth) { |
| 1409 | currentLine = testLine; |
| 1410 | } else { |
| 1411 | if (!currentLine.empty()) { |
| 1412 | lines.push_back(currentLine); |
| 1413 | // If the carried-over word itself exceeds maxWidth, truncate it and |
| 1414 | // push it as a complete line immediately — storing it in currentLine |
| 1415 | // would allow a subsequent short word to be appended after the ellipsis. |
| 1416 | if (getTextWidth(fontId, word.c_str(), style) > maxWidth) { |
| 1417 | lines.push_back(truncatedText(fontId, word.c_str(), maxWidth, style)); |
| 1418 | currentLine.clear(); |
| 1419 | if (static_cast<int>(lines.size()) >= maxLines) return lines; |
| 1420 | } else { |
| 1421 | currentLine = word; |
| 1422 | } |
| 1423 | } else { |
| 1424 | // Single word wider than maxWidth: truncate and stop to avoid complicated |
| 1425 | // splitting rules (different between languages). Results in an aesthetically |
| 1426 | // pleasing end. |
| 1427 | lines.push_back(truncatedText(fontId, word.c_str(), maxWidth, style)); |
| 1428 | return lines; |
| 1429 | } |
| 1430 | } |
| 1431 | } |
| 1432 | |
| 1433 | if (!currentLine.empty() && static_cast<int>(lines.size()) < maxLines) { |
no test coverage detected