HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
unicode_text_segmentation.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "unicode_grapheme_cluster_break.hpp"
8#include "unicode_description.hpp"
9
10namespace hi::inline v1 {
11
13 unicode_grapheme_cluster_break previous = unicode_grapheme_cluster_break::Other;
14 int RI_count = 0;
15 bool first_character = true;
16 bool in_extended_pictograph = false;
17
18 void reset() noexcept
19 {
20 previous = unicode_grapheme_cluster_break::Other;
21 RI_count = 0;
22 first_character = true;
23 in_extended_pictograph = false;
24 }
25};
26
34[[nodiscard]] bool breaks_grapheme(char32_t code_point, grapheme_break_state& state) noexcept;
35
36template<typename It, typename ItEnd>
37[[nodiscard]] std::vector<unicode_break_opportunity> unicode_grapheme_break(It first, ItEnd last) noexcept
38{
40 auto state = grapheme_break_state{};
41
42 for (auto it = first; it != last; ++it) {
43 hilet opertunity = breaks_grapheme(*it, state) ? unicode_break_opportunity::yes : unicode_break_opportunity::no;
44 r.push_back(opertunity);
45 }
46
47 r.push_back(unicode_break_opportunity::yes);
48 return r;
49}
50
66void wrap_lines(auto first, auto last, float max_width, auto get_width, auto get_code_point, auto set_code_point) noexcept
67{
68 using enum unicode_general_category;
69
70 auto it_at_last_space = last;
71 float width_at_last_space = 0.0;
72 float current_width = 0.0;
73
74 for (auto it = first; it != last; ++it) {
75 hilet code_point = get_code_point(*it);
76 hilet description = unicode_description::find(code_point);
77 hilet general_category = description->general_category();
78
79 if (general_category == Zp || general_category == Zl) {
80 // Reset the line on existing line and paragraph separator.
81 it_at_last_space = last;
82 width_at_last_space = 0.0f;
83 current_width = 0.0;
84 continue;
85
86 } else if (general_category == Zs) {
87 // Remember the length of the line at the end of the word.
88 it_at_last_space = it;
89 width_at_last_space = current_width;
90 }
91
92 current_width += get_width(*it);
93 if (current_width >= max_width && it_at_last_space != last) {
94 // The line is too long, replace the last space with a line separator.
95 set_code_point(*it, U'\u2028');
96 it_at_last_space = last;
97 width_at_last_space = 0.0f;
98 current_width = 0.0;
99 continue;
100 }
101 }
102}
103
104} // namespace hi::inline v1
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
bool breaks_grapheme(char32_t code_point, grapheme_break_state &state) noexcept
Check if for a grapheme break before the given code-point.
void wrap_lines(auto first, auto last, float max_width, auto get_width, auto get_code_point, auto set_code_point) noexcept
Wrap lines in text that are too wide.
Definition unicode_text_segmentation.hpp:66
Definition unicode_text_segmentation.hpp:12