-
-
Save alvesvaren/767d9585f0ecbef18ef1c7c0492c4332 to your computer and use it in GitHub Desktop.
| #include <vector> | |
| #include <string> | |
| #include <sstream> | |
| #include "esphome/components/display/display_buffer.h" | |
| #include "text_wrap.h" | |
| using namespace esphome; | |
| using namespace esphome::display; | |
| void wrap_text(DisplayBuffer* it, int x, int y, const char* text, Font* font, TextAlign align, float line_height) { | |
| // Calculate the bounds of a single space character | |
| int space_x1, space_y1, space_width, space_height; | |
| it->get_text_bounds(x, y, " ", font, align, &space_x1, &space_y1, &space_width, &space_height); | |
| // Break text into words | |
| std::vector<std::string> words; | |
| std::stringstream ss(text); | |
| std::string word; | |
| while (std::getline(ss, word, ' ')) { | |
| words.push_back(word); | |
| } | |
| // Initialize variables for the wrapped text | |
| int line_x = x; | |
| int line_y = y; | |
| int word_x1, word_y1, word_width, word_height; | |
| std::string line; | |
| // Iterate through the words and wrap them | |
| for (const auto& w : words) { | |
| it->get_text_bounds(line_x, line_y, w.c_str(), font, align, &word_x1, &word_y1, &word_width, &word_height); | |
| if (line_x + word_width >= it->get_width()) { | |
| // Print the current line and move to the next line | |
| it->printf(x, line_y, font, align, "%s", line.c_str()); | |
| line_y += static_cast<int>(word_height * line_height); | |
| line_x = x; | |
| // Clear the line buffer | |
| line.clear(); | |
| } | |
| // Add the word to the line buffer and move the cursor | |
| line += w; | |
| line_x += word_width + space_width; | |
| // If it's not the last word, add a space | |
| if (!line.empty() && &w != &words.back()) { | |
| line += " "; | |
| } | |
| } | |
| // Print the last line | |
| if (!line.empty()) { | |
| it->printf(x, line_y, font, align, "%s", line.c_str()); | |
| } | |
| } |
| #pragma once | |
| #include "esphome/components/display/display_buffer.h" | |
| void wrap_text( | |
| esphome::display::DisplayBuffer* it, int x, int y, | |
| const char* text, esphome::display::Font* font, | |
| esphome::display::TextAlign align, float line_height | |
| ); |
Thanks for this, it was very helpful. I had an urgent priority to add dad jokes to my e-paper display, least I die of boredom.
Note, I had to add #include esphome/components/font/font.h to text_wrap.cpp because it would error out on lack of reference to Font. I also needed to change Font* font to esphome::display::BaseFont* font on the wrap_text function for the same reason.
Perhaps you have a reference to Font somewhere else in your ESPHome config?
Anyway, it works like a charm! Thanks again.
This is great @alvesvaren. I have built on what you wrote, to make a printf format compatible version, that also allows you to specify a box anywhere on the screen (not just wrapping at the screen edge). Would you be willing for this to be added to the official esphome distribution?
If so, I am happy to create the pull request.
@davet2001 Sure, go for it! I just put this together pretty quickly for a project I had but it would be great to have it in esphome directly
For anyone else that finds this, the line in text_wrap.h needs to change to:
const char* text, esphome::font::Font* font,
Put the files in the esphome folder of your home assistant configuration.
Usage in yaml: