#include #include namespace raleigh { text_flower::text_flower(const char *s, uint32_t cols, uint32_t max_rows) : s(s), lines(max_rows ? max_rows : 10), offsets(max_rows ? max_rows : 10), max_rows(max_rows), cols(cols) { flow_text(); } __attribute__ ((pure)) uint32_t text_flower::get_n_lines() { return lines.n_entries; } __attribute__ ((pure)) char *text_flower::get_nth_line(uint32_t n) { return lines.buf[n]; } __attribute__ ((pure)) uint32_t text_flower::get_line_offset(uint32_t n) { return offsets.buf[n]; } void text_flower::draw_text(_pixel_t *start, uint32_t pitch, const struct font_info *fi, _pixel_t color) { for (uint32_t y = 0; y < lines.n_entries; ++y) { const char *line = lines.buf[y]; for (uint32_t x = 0; line[x]; ++x) put_char_no_bg(fi, line[x], start + y * fi->space_height * pitch + x * fi->space_width, pitch, color); } } void text_flower::push_line() { lines.add_back(strndup(line_start, row_len)); offsets.add_back(line_start - s); line_start = on_char; row_len = 0; if (max_rows && (lines.n_entries == max_rows)) on_char = ""; } void text_flower::flow_text() { for (uint32_t i = 0; i < lines.n_entries; ++i) free_block(lines.buf[i]); lines.n_entries = 0; offsets.n_entries = 0; line_start = on_char = s; row_len = 0; while (*on_char) { if (*on_char == '\n') { ++on_char; push_line(); } else if (*on_char == ' ') { ++on_char; if (row_len != 0) { if (++row_len == cols) push_line(); } else ++line_start; } else { uint32_t word_len = str_find_any(on_char, " \n"); if (!cols) { row_len += word_len; on_char += word_len; } else if (row_len + word_len <= cols) { row_len += word_len; on_char += word_len; if (row_len == cols) push_line(); } else if (word_len > cols) { on_char += cols - row_len; row_len = cols; push_line(); } else push_line(); } } if (row_len && (!max_rows || (lines.n_entries != max_rows))) push_line(); } }