HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
font_weight.hpp
1// Copyright Take Vos 2021.
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 "../exception.hpp"
8#include "../strings.hpp"
9#include "../concepts.hpp"
10#include <string>
11#include <unordered_map>
12#include <ostream>
13#include <array>
14
15namespace hi::inline v1 {
16
17enum class font_weight {
18 Thin,
19 ExtraLight,
20 Light,
21 Regular,
22 Medium,
23 SemiBold,
24 Bold,
25 ExtraBold,
26 Black,
27 ExtraBlack,
28};
29
30inline hilet font_weight_from_string_table = std::unordered_map<std::string, font_weight>{
31 {"thin", font_weight::Thin},
32 {"hairline", font_weight::Thin},
33 {"ultra-light", font_weight::ExtraLight},
34 {"ultra light", font_weight::ExtraLight},
35 {"extra-light", font_weight::ExtraLight},
36 {"extra light", font_weight::ExtraLight},
37 {"light", font_weight::Light},
38 {"normal", font_weight::Regular},
39 {"regular", font_weight::Regular},
40 {"medium", font_weight::Medium},
41 {"semi-bold", font_weight::SemiBold},
42 {"semi bold", font_weight::SemiBold},
43 {"demi-bold", font_weight::SemiBold},
44 {"demi bold", font_weight::SemiBold},
45 {"bold", font_weight::Bold},
46 {"extra-bold", font_weight::ExtraBold},
47 {"extra bold", font_weight::ExtraBold},
48 {"ultra-bold", font_weight::ExtraBold},
49 {"ultra bold", font_weight::ExtraBold},
50 {"heavy", font_weight::Black},
51 {"black", font_weight::Black},
52 {"extra-black", font_weight::ExtraBlack},
53 {"ultra-black", font_weight::ExtraBlack},
54};
55
58[[nodiscard]] constexpr font_weight font_weight_from_int(numeric_integral auto rhs)
59{
60 if (rhs < 50 || rhs > 1000) {
61 throw parse_error(std::format("Unknown font-weight {}", rhs));
62 }
63 return static_cast<font_weight>(((rhs + 50) / 100) - 1);
64}
65
66[[nodiscard]] inline font_weight font_weight_from_string(std::string_view rhs)
67{
68 hilet i = font_weight_from_string_table.find(to_lower(rhs));
69 if (i == font_weight_from_string_table.end()) {
70 throw parse_error(std::format("Unknown font-weight {}", rhs));
71 }
72 return i->second;
73}
74
75[[nodiscard]] constexpr char const *to_const_string(font_weight const &x) noexcept
76{
77 switch (x) {
78 case font_weight::Thin: return "Thin";
79 case font_weight::ExtraLight: return "ExtraLight";
80 case font_weight::Light: return "Light";
81 case font_weight::Regular: return "Regular";
82 case font_weight::Medium: return "Medium";
83 case font_weight::SemiBold: return "SemiBold";
84 case font_weight::Bold: return "Bold";
85 case font_weight::ExtraBold: return "ExtraBold";
86 case font_weight::Black: return "Black";
87 case font_weight::ExtraBlack: return "ExtraBlack";
88 default: hi_no_default();
89 }
90}
91
92[[nodiscard]] inline std::string to_string(font_weight const &x) noexcept
93{
94 return to_const_string(x);
95}
96
97[[nodiscard]] inline char to_char(font_weight const &x) noexcept
98{
99 hilet x_ = static_cast<int>(x);
100 hi_axiom(x_ >= 0 && x_ <= 9);
101 return static_cast<char>('0' + x_);
102}
103
104[[nodiscard]] constexpr int to_int(font_weight const &x) noexcept
105{
106 hilet x_ = (static_cast<int>(x) + 1) * 100;
107 return (x_ == 1000) ? 950 : x_;
108}
109
110inline std::ostream &operator<<(std::ostream &lhs, font_weight const &rhs)
111{
112 return lhs << to_string(rhs);
113}
114
115inline bool almost_equal(font_weight const &lhs, font_weight const &rhs) noexcept
116{
117 // Check only if it is bold or not.
118 return (lhs > font_weight::Medium) == (rhs > font_weight::Medium);
119}
120
121[[nodiscard]] constexpr auto font_weight_alternative_table_generator() noexcept
122{
123 std::array<font_weight, 100> r = {font_weight::Regular};
124
125 for (auto w = 0_uz; w < 10_uz; ++w) {
126 auto min_w = w;
127 auto max_w = w;
128 auto new_w = w;
129 auto forward = false;
130
131 for (auto i = 0_uz; i < 10_uz; ++i) {
132 r[w * 10_uz + i] = static_cast<font_weight>(new_w);
133
134 // Change direction to not overflow.
135 if ((forward and max_w == 9_uz) or (not forward and min_w == 0_uz)) {
136 forward = not forward;
137 }
138
139 new_w = forward ? ++max_w : --min_w;
140
141 // Change direction to zig-zag.
142 forward = not forward;
143 }
144 }
145 return r;
146}
147
148constexpr auto font_weight_alternative_table = font_weight_alternative_table_generator();
149
150[[nodiscard]] constexpr font_weight font_weight_alterative(font_weight weight, int i) noexcept
151{
152 hi_axiom(i >= 0 && i < 10);
153 auto w = static_cast<int>(weight);
154 hi_axiom(w >= 0 && w < 10);
155 return font_weight_alternative_table[(w * 10) + i];
156}
157
158} // namespace hi::inline v1
159
160template<typename CharT>
161struct std::formatter<hi::font_weight, CharT> : std::formatter<char const *, CharT> {
162 auto format(hi::font_weight const &t, auto &fc)
163 {
164 return std::formatter<char const *, CharT>::format(hi::to_const_string(t), fc);
165 }
166};
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
T forward(T... args)
T to_string(T... args)