HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
unicode_bidi.hpp
1// Copyright Take Vos 2020-2022.
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_bidi_class.hpp"
8#include "unicode_description.hpp"
9#include "../assert.hpp"
10
11namespace hi::inline v1 {
12
14 enum class mode_type : uint8_t { LTR, RTL, auto_LTR, auto_RTL };
15
16 mode_type direction_mode = mode_type::auto_LTR;
17 bool enable_mirrored_brackets = true;
18 bool enable_line_separator = true;
19
20 constexpr unicode_bidi_context() noexcept = default;
21 constexpr unicode_bidi_context(unicode_bidi_context const&) noexcept = default;
22 constexpr unicode_bidi_context(unicode_bidi_context&&) noexcept = default;
23 constexpr unicode_bidi_context& operator=(unicode_bidi_context const&) noexcept = default;
24 constexpr unicode_bidi_context& operator=(unicode_bidi_context&&) noexcept = default;
25
26 constexpr unicode_bidi_context(unicode_bidi_class text_direction) noexcept {
27 if (text_direction == unicode_bidi_class::L) {
28 direction_mode = mode_type::auto_LTR;
29 } else if (text_direction == unicode_bidi_class::R) {
30 direction_mode = mode_type::auto_RTL;
31 } else {
33 }
34 }
35};
36
37namespace detail {
38
43
47
51 char32_t code_point;
52
57
62
67
68 [[nodiscard]] unicode_bidi_char_info(std::size_t index, char32_t code_point, unicode_description const *description) noexcept
69 :
70 index(index),
71 description(description),
72 code_point(code_point),
73 embedding_level(0),
74 direction(description->bidi_class()),
75 bidi_class(description->bidi_class())
76 {
77 }
78
82 [[nodiscard]] unicode_bidi_char_info(std::size_t index, unicode_bidi_class bidi_class) noexcept :
83 index(index),
84 code_point(U'\ufffd'),
85 direction(bidi_class),
86 bidi_class(bidi_class),
87 embedding_level(0),
88 description(nullptr)
89 {
90 }
91};
92
93using unicode_bidi_char_info_vector = std::vector<unicode_bidi_char_info>;
94using unicode_bidi_char_info_iterator = unicode_bidi_char_info_vector::iterator;
95using unicode_bidi_char_info_const_iterator = unicode_bidi_char_info_vector::const_iterator;
96
99
100 characters_type characters;
101
102 template<typename... Args>
103 void emplace_character(Args&&...args) noexcept
104 {
105 characters.emplace_back(std::forward<Args>(args)...);
106 }
107};
108
109template<typename OutputIt, typename SetCodePoint, typename SetTextDirection>
110static void unicode_bidi_L4(
111 unicode_bidi_char_info_iterator first,
112 unicode_bidi_char_info_iterator last,
113 OutputIt output_it,
114 SetCodePoint set_code_point,
115 SetTextDirection set_text_direction) noexcept
116{
117 for (auto it = first; it != last; ++it, ++output_it) {
118 hilet text_direction = it->embedding_level % 2 == 0 ? unicode_bidi_class::L : unicode_bidi_class::R;
119 set_text_direction(*output_it, text_direction);
120 if (it->direction == unicode_bidi_class::R && it->description->bidi_bracket_type() != unicode_bidi_bracket_type::n) {
121 set_code_point(*output_it, it->description->bidi_mirroring_glyph());
122 }
123 }
124}
125
126[[nodiscard]] std::pair<int8_t, unicode_bidi_class> unicode_bidi_P2_P3(
127 unicode_bidi_char_info_iterator first,
128 unicode_bidi_char_info_iterator last,
129 unicode_bidi_context const& context = {}) noexcept;
130
132 unicode_bidi_char_info_iterator first,
133 unicode_bidi_char_info_iterator last,
134 unicode_bidi_context const& context = {}) noexcept;
135
136} // namespace detail
137
161template<typename It, typename GetDescription, typename SetCodePoint, typename SetTextDirection>
163 It first,
164 It last,
165 GetDescription get_description,
166 SetCodePoint set_code_point,
167 SetTextDirection set_text_direction,
168 unicode_bidi_context const& context = {})
169{
170 auto proxy = detail::unicode_bidi_char_info_vector{};
171 proxy.reserve(std::distance(first, last));
172
173 std::size_t index = 0;
174 for (auto it = first; it != last; ++it) {
175 hilet[code_point, description_ptr] = get_description(*it);
176 proxy.emplace_back(index++, code_point, description_ptr);
177 }
178
179 auto [proxy_last, paragraph_directions] = detail::unicode_bidi_P1(begin(proxy), end(proxy), context);
180 last = shuffle_by_index(first, last, begin(proxy), proxy_last, [](hilet& item) {
181 return item.index;
182 });
183
184 detail::unicode_bidi_L4(
185 begin(proxy),
186 proxy_last,
187 first,
188 std::forward<SetCodePoint>(set_code_point),
189 std::forward<SetTextDirection>(set_text_direction));
190 return {last, std::move(paragraph_directions)};
191}
192
201template<typename It, typename GetDescription>
202[[nodiscard]] unicode_bidi_class
203unicode_bidi_direction(It first, It last, GetDescription get_description, unicode_bidi_context const& context = {})
204{
205 auto proxy = detail::unicode_bidi_char_info_vector{};
206 proxy.reserve(std::distance(first, last));
207
208 std::size_t index = 0;
209 for (auto it = first; it != last; ++it) {
210 hilet[code_point, description_ptr] = get_description(*it);
211 proxy.emplace_back(index++, code_point, description_ptr);
212 if (proxy.back().direction == unicode_bidi_class::B) {
213 // Break early when end-of-paragraph symbol is found.
214 break;
215 }
216 }
217
218 return detail::unicode_bidi_P2_P3(begin(proxy), end(proxy), context).second;
219}
220
231template<typename It, typename EndIt, typename DescriptionFunc>
232It unicode_bidi_control_filter(It first, EndIt last, DescriptionFunc const& description_func)
233{
234 return std::remove_if(first, last, [&](hilet& item) {
235 return is_control(description_func(item).bidi_class());
236 });
237}
238
239} // namespace hi::inline v1
Utilities to assert and bound check.
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:148
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
auto shuffle_by_index(auto first, auto last, auto indices_first, auto indices_last, auto index_op) noexcept
Shuffle a container based on a list of indices.
Definition algorithm.hpp:260
unicode_bidi_class unicode_bidi_direction(It first, It last, GetDescription get_description, unicode_bidi_context const &context={})
Get the unicode bidi direction for the first paragraph and context.
Definition unicode_bidi.hpp:203
unicode_bidi_class
Bidirectional class Unicode Standard Annex #9: https://unicode.org/reports/tr9/.
Definition unicode_bidi_class.hpp:17
It unicode_bidi_control_filter(It first, EndIt last, DescriptionFunc const &description_func)
Removes control characters which will not survive the bidi-algorithm.
Definition unicode_bidi.hpp:232
std::pair< It, std::vector< unicode_bidi_class > > unicode_bidi(It first, It last, GetDescription get_description, SetCodePoint set_code_point, SetTextDirection set_text_direction, unicode_bidi_context const &context={})
Reorder a given range of characters based on the unicode_bidi algorithm.
Definition unicode_bidi.hpp:162
Definition unicode_bidi.hpp:13
Definition unicode_bidi.hpp:39
unicode_bidi_class direction
Current computed direction of the code-point.
Definition unicode_bidi.hpp:61
unicode_description const * description
Description of the code-point.
Definition unicode_bidi.hpp:46
int8_t embedding_level
The embedding level.
Definition unicode_bidi.hpp:56
unicode_bidi_class bidi_class
The original bidi class of the code-point.
Definition unicode_bidi.hpp:66
std::size_t index
Index from the first character in the original list.
Definition unicode_bidi.hpp:42
char32_t code_point
The current code point.
Definition unicode_bidi.hpp:51
unicode_bidi_char_info(std::size_t index, unicode_bidi_class bidi_class) noexcept
Constructor for testing to bypass normal initialization.
Definition unicode_bidi.hpp:82
Definition unicode_bidi.hpp:97
Description of a unicode code point.
Definition unicode_description.hpp:33
constexpr unicode_bidi_class bidi_class() const noexcept
The bidi class of this code-point This function is used by the bidirectional algorithm to figure out ...
Definition unicode_description.hpp:135
T begin(T... args)
T distance(T... args)
T emplace_back(T... args)
T end(T... args)
T move(T... args)
T remove_if(T... args)