HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
text_style.hpp
1// Copyright Take Vos 2021-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 "text_decoration.hpp"
8#include "semantic_text_style.hpp"
9#include "../color/color.hpp"
10#include "../i18n/i18n.hpp"
11#include "../unicode/unicode.hpp"
12#include "../utility/utility.hpp"
13#include "../font/font.hpp"
14#include "../telemetry/telemetry.hpp"
15#include "../container/container.hpp"
16#include "../macros.hpp"
17#include <ostream>
18#include <vector>
19#include <algorithm>
20
21hi_export_module(hikogui.text.text_style);
22
23hi_export namespace hi::inline v1 {
24
26 phrasing_mask phrasing_mask;
27 iso_639 language_filter;
28 iso_15924 script_filter;
29
30 font_family_id family_id;
31 ::hi::color color;
32 font_size_s size;
33 font_variant variant;
34 text_decoration decoration;
35
36 text_sub_style() noexcept = default;
37
39 hi::phrasing_mask phrasing_mask,
40 iso_639 language_filter,
41 iso_15924 script_filter,
42 font_family_id family_id,
43 font_variant variant,
44 font_size_s size,
45 ::hi::color color,
46 text_decoration decoration) noexcept :
47 phrasing_mask(phrasing_mask),
48 language_filter(language_filter),
49 script_filter(script_filter),
50 family_id(family_id),
51 color(color),
52 size(size),
53 variant(variant),
54 decoration(decoration)
55 {
56 }
57
58 [[nodiscard]] size_t hash() const noexcept
59 {
60 auto r = 0_uz;
61 r ^= std::hash<hi::phrasing_mask>{}(phrasing_mask);
62 r ^= std::hash<iso_639>{}(language_filter);
63 r ^= std::hash<iso_15924>{}(script_filter);
64 r ^= std::hash<font_family_id>{}(family_id);
65 r ^= std::hash<hi::color>{}(color);
66 r ^= std::hash<font_size_s>{}(size);
67 r ^= std::hash<font_variant>{}(variant);
68 r ^= std::hash<text_decoration>{}(decoration);
69 return r;
70 }
71
72 [[nodiscard]] length_f cap_height() const noexcept
73 {
74 auto const& font = find_font(family_id, variant);
75 return font.metrics.cap_height * size;
76 }
77
78 [[nodiscard]] length_f x_height() const noexcept
79 {
80 auto const& font = find_font(family_id, variant);
81 return font.metrics.x_height * size;
82 }
83
84 [[nodiscard]] bool matches(phrasing phrasing, iso_639 language, iso_15924 script) const noexcept
85 {
86 if (not to_bool(phrasing_mask & to_phrasing_mask(phrasing))) {
87 return false;
88 }
89 if (language_filter and language and language_filter != language) {
90 return false;
91 }
92 if (script_filter and script and script_filter != script) {
93 return false;
94 }
95 return true;
96 }
97
98 [[nodiscard]] friend bool operator==(text_sub_style const&, text_sub_style const&) noexcept = default;
99};
100
101} // namespace hi::inline v1
102
103template<>
104struct std::hash<hi::text_sub_style> {
105 [[nodiscard]] size_t operator()(hi::text_sub_style const& rhs) const noexcept
106 {
107 return rhs.hash();
108 }
109};
110
111hi_export namespace hi::inline v1::detail {
112
115 using reference = value_type const&;
117 using iterator = vector_type::const_iterator;
118
119 vector_type _sub_styles;
120
121 constexpr text_style_impl() noexcept = default;
122
123 text_style_impl(std::vector<text_sub_style> sub_styles) noexcept : _sub_styles(std::move(sub_styles))
124 {
125 hi_assert(not empty());
126 hi_assert(all(back().phrasing_mask));
127 hi_assert(back().language_filter.empty());
128 hi_assert(back().script_filter.empty());
129 }
130
131 [[nodiscard]] bool empty() const noexcept
132 {
133 return _sub_styles.empty();
134 }
135
136 explicit operator bool() const noexcept
137 {
138 return not empty();
139 }
140
141 [[nodiscard]] size_t hash() const noexcept
142 {
143 auto r = 0_uz;
144 for (auto const& sub_style : _sub_styles) {
145 r ^= std::hash<text_sub_style>{}(sub_style);
146 }
147 return r;
148 }
149
150 [[nodiscard]] reference back() const noexcept
151 {
152 return _sub_styles.back();
153 }
154
155 [[nodiscard]] iterator begin() const noexcept
156 {
157 return _sub_styles.begin();
158 }
159
160 [[nodiscard]] iterator end() const noexcept
161 {
162 return _sub_styles.end();
163 }
164
165 [[nodiscard]] constexpr friend bool operator==(text_style_impl const&, text_style_impl const&) noexcept = default;
166};
167
168} // namespace hi::inline v1::detail
169
170template<>
171struct std::hash<hi::detail::text_style_impl> {
172 [[nodiscard]] size_t operator()(hi::detail::text_style_impl const& rhs) const noexcept
173 {
174 return rhs.hash();
175 }
176};
177
178hi_export namespace hi::inline v1 {
179namespace detail {
180inline auto text_styles = stable_set<text_style_impl>{};
181}
182
184public:
185 using int_type = uint16_t;
186
187 constexpr text_style() : _value(0xffff) {}
188 constexpr text_style(text_style const&) noexcept = default;
189 constexpr text_style(text_style&&) noexcept = default;
190 constexpr text_style& operator=(text_style const&) noexcept = default;
191 constexpr text_style& operator=(text_style&&) noexcept = default;
192 [[nodiscard]] constexpr friend bool operator==(text_style const&, text_style const&) noexcept = default;
193
194 constexpr text_style(semantic_text_style rhs) noexcept : _value(0xff00 + std::to_underlying(rhs)) {}
195
197 {
198 auto const index = detail::text_styles.emplace(std::move(rhs));
199 if (index < 0xff00) {
200 _value = narrow_cast<uint16_t>(index);
201 } else {
202 hi_log_error_once("text-style:error:too-many", "Too many text-styles");
203 // semantic text-style "label".
204 _value = 0xff00;
205 }
206 }
207
208 [[nodiscard]] constexpr bool empty() const noexcept
209 {
210 return _value == 0xffff;
211 }
212
213 constexpr explicit operator bool() const noexcept
214 {
215 return not empty();
216 }
217
218 [[nodiscard]] constexpr bool is_semantic() const noexcept
219 {
220 hi_assert(not empty());
221 return _value >= 0xff00;
222 }
223
224 constexpr explicit operator semantic_text_style() const noexcept
225 {
226 return static_cast<semantic_text_style>(narrow_cast<std::underlying_type_t<semantic_text_style>>(_value - 0xff00));
227 }
228
229 text_sub_style const *operator->() const noexcept
230 {
231 hi_axiom(not empty());
232 if (_value < 0xff00) {
233 return std::addressof(detail::text_styles[_value].back());
234 } else {
235 hi_not_implemented();
236 }
237 }
238
239 text_sub_style const& operator*() const noexcept
240 {
241 hi_axiom(not empty());
242 if (_value < 0xff00) {
243 return detail::text_styles[_value].back();
244 } else {
245 hi_not_implemented();
246 }
247 }
248
249 text_sub_style const& sub_style(phrasing phrasing, iso_639 language, iso_15924 script) const noexcept
250 {
251 for (auto const& style : detail::text_styles[_value]) {
252 if (style.matches(phrasing, language, script)) {
253 return style;
254 }
255 }
256 hi_no_default();
257 }
258
259private:
260 int_type _value;
261};
262
263} // namespace hi::inline v1
Defined the color type.
phrasing
Phrasing.
Definition phrasing.hpp:33
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
text_decoration
Describes how a grapheme should be underlined when rendering the text.
Definition text_decoration.hpp:24
hi_export font const & find_font(font_family_id family_id, font_variant variant=font_variant{}) noexcept
Find a font closest to the variant.
Definition font_book.hpp:415
constexpr bool matches(phrasing_mask const &lhs, phrasing const &rhs) noexcept
Check if the text-phrasing is included in the text-phrasing-mask.
Definition phrasing.hpp:230
This is a RGBA floating point color.
Definition color_intf.hpp:49
Definition font_font.hpp:31
font_metrics_em metrics
The metrics of a font.
Definition font_font.hpp:65
au::Quantity< Unit, T > cap_height
Height of capital letter, or height of the letter 'H'.
Definition font_metrics.hpp:41
au::Quantity< Unit, T > x_height
Height of lower case characters without ascenders or descenders, or the small letter 'x'.
Definition font_metrics.hpp:45
A font variant is one of 16 different fonts that can be part of a family.
Definition font_variant.hpp:27
ISO-639 language code.
Definition iso_639.hpp:29
Definition text_style.hpp:25
Definition text_style.hpp:113
Definition text_style.hpp:183
T addressof(T... args)
T back(T... args)
T begin(T... args)
T empty(T... args)
T end(T... args)
T move(T... args)
T operator()(T... args)